Multi-Modal Fusion Transformer for End-to-End Autonomous Driving

Multi-Modal Fusion Transformer for End-to-End Autonomous Driving

摘要

自动驾驶中应该如何整合来自补充传感器的表示?基于几何的传感器融合在感知任务,如目标检测和运动预测方面显示出巨大前景。然而,对于实际驾驶任务来说,3D场景的全局上下文是关键的,例如,交通灯状态的变化可能会影响几何上远离该交通灯的车辆的行为。因此,几何本身可能不足以在端到端驾驶模型中有效地融合表示。在这项工作中,我们展示了基于现有传感器融合方法的模仿学习策略在面对高密度动态代理和复杂场景时表现不佳,这些场景需要全局上下文推理,例如处理来自多个方向的未受控交叉路口的交通。因此,我们提出了TransFuser,一种新颖的多模态融合变换器,使用注意力机制整合图像和激光雷达表示。我们使用CARLA城市驾驶模拟器在涉及复杂场景的城市环境中验证了我们方法的有效性。我们的方法实现了最先进的驾驶性能,与基于几何融合相比,碰撞减少了76%。
在这里插入图片描述

  • 动机:激光雷达无法反应交通灯状态;相机看不到旁边红色交通车(但是环视摄像头是能够看到的,因此这个动机稍弱)
  • 思考:激光雷达是否必不可少,纯视觉的路线是否存在问题? 多模态融合和单一视觉融合优势和劣势分别是什么?

1.引言

仅图像[16, 8, 41, 3, 42, 64, 53]和仅激光雷达[46, 23]的方法最近在端到端驾驶方面显示出令人印象深刻的结果。然而,这些研究主要关注于动态代理数量有限的场景,并假设场景中其他代理的行为近乎理想。随着最近CARLA[21]版本的对抗性场景的引入,例如闯红灯的车辆、未受控的四路交叉路口,或从遮挡区域突然出现的行人在随机位置过马路,仅使用图像的方法表现不佳(表1),因为它们缺乏场景的3D信息。

尽管激光雷达包含3D信息,激光雷达测量通常非常稀疏(特别是在远处),并且需要额外的传感器来捕获激光雷达扫描中缺失的信息,例如交通灯状态。虽然大多数现有的端到端驾驶方法专注于单一输入模态,自动驾驶系统通常配备了相机和激光雷达传感器[21, 47, 25, 59, 17, 26, 48, 1, 62]。这引发了重要的问题:我们能否整合这两种模态的表示,以利用它们互补的优势进行自动驾驶?我们应该在多大程度上独立处理不同的模态,以及我们应该采用什么样的融合机制以获得最大的性能提升?在传感器融合领域的先前工作主要集中在驾驶的感知方面,例如2D和3D目标检测[22, 12, 66, 9, 44, 31, 34, 61, 33, 37],运动预测[22, 36, 5, 35, 63, 6, 19, 38, 32, 9]和深度估计[24, 60, 61, 33]。这些方法专注于学习一个状态表示,捕获3D场景的几何和语义信息。它们主要基于图像空间和不同的激光雷达投影空间之间的几何特征投影,例如鸟瞰图(BEV)[22, 12, 66, 9, 44, 31, 34, 61, 33]和测距图(RV)[39, 37, 22, 38, 9, 51]。信息通常从2D或3D空间中投影的2D或3D空间中的每个特征的局部邻域中聚合。虽然这些方法的表现优于仅使用图像的方法,我们观察到它们架构设计中的局部性假设限制了它们在复杂城市场景中的表现(表1a)。例如,在处理交叉口的交通时,自车需要考虑多个动态代理和交通灯之间的相互作用(图1)。虽然深度卷积网络可以用来捕获单个模态内的全局上下文,但将它们扩展到多个模态或对特征对之间的交互进行建模并非易事。为了克服这些限制,我们使用变换器的注意力机制[54]将关于3D场景的全局上下文推理直接整合到不同模态的特征提取层中。我们考虑单视图图像和激光雷达输入,因为它们在表示场景方面是互补的,我们的重点是整合不同类型模态的表示。我们将得到的模型称为TransFuser,并将其整合到一个用于端到端驾驶的自回归航点预测框架中(图2)。

贡献:
(1)我们展示了基于现有传感器融合方法的模仿学习策略在处理城市驾驶中的对抗性场景时无法应对,例如交叉口的无保护转弯或从遮挡区域突然出现的行人。
(2)我们提出了一种新颖的多模态融合变换器(TransFuser),将3D场景的全局上下文整合到不同模态的特征提取层中。
(3)我们在CARLA中复杂城市环境涉及对抗性场景的实验中验证了我们的方法,并实现了最先进的性能。我们的代码和训练模型可在https://github.com/autonomousvision/transfuser找到。

  • 个人总结:总体上是说单一的视觉信息缺乏场景的3D信息。单一的激光雷达虽然包含3D信息,但是测量通常稀疏(对于远处),并且无法感知交通灯状态。因此出发点是融合两种感知模态;之前的工作对多个模态交互建模并非易事。为了克服这些限制,采用了transformer
  • 问题:视觉和雷达数据非时序;不是环视的摄像头感知数据
  • 贡献:第一点贡献我不知道算不算贡献,直觉上是呈现了一种单一传感器都无法解决的情况;第二个贡献算是模型架构(用transformer融合了不同模态);第三个贡献工作量吧

2. 相关工作

2.1 多模态自动驾驶

近期的多模态方法用于端到端驾驶已经表明,将RGB图像与深度和语义信息相结合,可以潜在地提升驾驶性能。Xiao等人[58]从早期、中期和晚期融合相机和深度模态的角度进行探索,并观察到显著的性能提升。Behl等人[3]和Zhou等人[65]展示了语义和深度作为驾驶的显式中间表示的有效性。在本项工作中,我们专注于图像和激光雷达输入,因为它们在场景表示方面是互补的,并且通常在自动驾驶系统中可用。在这方面,Sobh等人[51]利用后期融合架构处理激光雷达和图像模态,其中每个输入在单独的流中进行编码,然后连接在一起。然而,我们观察到,由于无法解释多个动态代理的行为,这种融合机制在复杂城市场景中导致高违规率(表1b)。因此,我们提出了一种新颖的多模态融合变换器,它在特征编码过程中的多个阶段有效地整合了来自不同模态的信息,从而克服了后期融合方法的局限性。

2.2 目标检测和运动预测的传感器融合方法

大多数关于传感器融合的工作都集中在感知任务上,例如目标检测[22, 12, 66, 7, 44, 31, 34, 61, 33, 37]和运动预测[36, 5, 35, 63, 6, 19, 38]。它们操作多视图激光雷达,例如鸟瞰图(BEV)和测距图(RV),或者通过将激光雷达特征投影到图像空间或将图像特征投影到BEV或RV空间来补充相机输入。与我们的方法最接近的是ContFuse[34],它在图像和激光雷达BEV特征之间执行多尺度密集特征融合。对于激光雷达BEV表示中的每个像素,它计算3D空间中局部邻域内的最近邻,将这些邻近点投影到图像空间以获得相应的图像特征,使用连续卷积聚合这些特征,并将其与激光雷达BEV特征结合。其他基于投影的融合方法也遵循类似的趋势,从2D或3D空间的局部邻域中聚合信息。然而,这些方法学习到的状态表示是不充分的,因为它们没有捕获3D场景的全局上下文,这在对抗性场景中进行安全操作是重要的。为了证明这一点,我们实现了一种多尺度基于几何的融合机制,受到[34, 33]的启发,涉及图像到激光雷达和激光雷达到图像特征融合,用于CARLA中的端到端驾驶,并观察到在复杂城市设置中的高违规率(表1b)。为了克服这个限制,我们提出了一种基于注意力的多模态融合变换器,它整合了全局上下文推理,并实现了更优越的驾驶性能。

2.3 自动驾驶中的注意力机制

注意力机制已经被探索用于驾驶的上下文,例如变道[13]、目标检测[11, 32]和运动预测[32, 50, 49, 28, 15, 30, 29, 56]。Chen等人[11]使用循环注意力机制预测车辆控制,该机制在为车辆控制预测学习到的语义图上。Li等人[32]利用注意力来捕获参与者之间的时间和空间依赖性,通过将变换器模块整合到循环神经网络中。SA-NMP[56]是一项并行工作,它学习在从2D CNN提取的特征上学习注意力掩码,操作激光雷达BEV投影和HD地图,专注于动态代理以实现安全的运动规划。Chen等人[13]在TORCS赛车模拟器中利用注意力进行变道时关注周围车辆,在分层深度强化学习框架中使用注意力。他们整合了一个空间注意力模块来检测图像中最相关的区域,以及一个时间注意力模块来加权不同的时间步图像输入,从而实现更平滑的变道。然而,这些方法都没有考虑多个模态或编码3D场景的全局上下文,这对于安全导航对抗性场景是必要的。相反,我们展示了注意力在不同模态之间的特征融合对于具有挑战性的城市驾驶场景的有效性。

3. 方法

在这项工作中,我们提出了一个端到端驾驶架构(图2),包含两个主要组件:(1) 多模态融合变换器,用于整合多个模态(单视图图像和激光雷达)的信息,以及(2) 自回归航点预测网络。以下部分详细介绍了我们的问题设置、输入和输出参数化以及模型的每个组件。
测事实上事实上事实上是

  • 这个架构中有个问题是LIDAR的BEV是二维的了,损失了LiDAR的三维信息;这个代码不是这篇论文的,而是发在PAMI那篇论文上的

3.1 问题设置

我们考虑城市环境中的点对点导航任务[23, 45, 46, 8, 16],目标是在安全地对其他动态代理做出反应并遵循交通规则的同时完成给定路线。模仿学习(IL):IL的目标是学习一个策略π,该策略模仿专家策略π*的行为。在我们的设置中,策略是从输入到航点的映射,这些航点提供给单独的低级控制器以输出动作。我们考虑行为克隆(BC)方法的IL,这是一种监督学习方法。首先在环境中部署专家策略,收集数据集 D = { ( X i , W i ) i = 1 Z } \mathcal{D} =\{{ (\mathcal{X}^i, \mathcal{W}^i)}^Z_{i=1}\} D={(Xi,Wi)i=1Z},大小为Z,包括环境的高维观测 X \mathcal{X} X和相应的专家轨迹,定义为BEV空间中的一组2D航点,即 W = { w t = ( x t , y t ) } t = 1 T \mathcal{W} = \{\mathbf {w}_t = (xt, yt)\}^T_{t=1} W={wt=(xt,yt)}t=1T。这个BEV空间使用自车坐标系。策略 π \pi π是使用收集到的数据 D \mathcal{D} D以监督方式训练的,损失函数为L。

arg ⁡ min ⁡ π E ( X , W ) ∼ D [ L ( W , π ( X ) ) ] (1) \arg\min_{\pi} \mathbb{E}_{(\mathcal{X},\mathcal{W}) \sim \mathcal{D}} [L(\mathcal{W}, \pi(\mathcal{X}))] \tag{1} argπminE(X,W)D[L(W,π(X))](1)

高维观测 X \mathcal{X} X 包括前向相机图像输入和来自单个时间步的激光雷达点云。我们使用单个时间步输入,因为之前关于自动驾驶的模仿学习研究已经表明使用观测历史可能不会带来性能提升。我们使用预测轨迹 π ( X ) \pi(\mathcal{X}) π(X) 和专家轨迹 W \mathcal{W} W 之间的L1距离作为损失函数。我们假设可以使用逆动力学模型,实现为 PID 控制器,执行低级控制,即转向、油门和制动,提供未来轨迹 W \mathcal{W} W。动作确定为 a = I ( W ) a = I(\mathcal{W}) a=I(W)。全局规划器:我们遵循 CARLA 0.9.10 的标准协议,假设提供了高层次的目标位置 G G G,作为 GPS 坐标。注意,这些目标位置是稀疏的,并且可以相隔数百米,与策略 π \pi π 预测的局部航点相比。
\subsection*{输入和输出参数化}

3.2 输入和输出参数化

输入表示:按照先前的工作,我们将激光雷达点云转换为一个在二维鸟瞰图(BEV)网格上的2-bin直方图,具有固定分辨率。我们考虑自车前方32米内和每侧16米的点,从而包含一个32m × \times × 32m的BEV网格。我们将网格划分为0.125m × \times × 0.125m的区块,这导致了一个256 × \times × 256像素的分辨率。对于直方图,我们将高度维度离散化为2个bin,代表地面上/下方的点。这导致了一个大小为256 × \times × 256像素的双通道伪图像。对于RGB输入,我们考虑具有100°视场的前向相机。我们以400 × \times × 300像素的分辨率提取前向图像,裁剪到256 × \times × 256以去除边缘的径向失真。

输出表示:我们预测自车在BEV空间中的未来轨迹 W W W,以自车的当前坐标系为中心。轨迹由一系列2D航点 { w t = ( x t , y t ) } t = 1 T \{w_t = (x_t, y_t)\}_{t=1}^T {wt=(xt,yt)}t=1T 表示。我们使用 T = 4 T = 4 T=4,这是我们的逆动力学模型所需的航点数量默认值。

3.3 多模态融合变换器

我们的主要思想是利用变换器的自注意力机制来整合图像和激光雷达模态的全局上下文,因为它们在补充性质上是互补的。变换器架构的输入由一系列离散标记组成,每个标记由特征向量表示。特征向量通过位置编码进行补充,以加入位置归纳偏差。形式上,我们将输入序列表示为 F i n ∈ R N × D f F_{in} \in \mathbb{R}^{N \times D_f} FinRN×Df,其中 N N N 是序列中的标记数量,每个标记由维度为 D f D_f Df 的特征向量表示。变换器使用线性投影计算一组查询、键和值 ( Q , K , V ) (Q, K, V) (Q,K,V)

Q = F i n M q , K = F i n M k , V = F i n M v (2) Q = F_{in}M_q, \quad K = F_{in}M_k, \quad V = F_{in}M_v \tag{2} Q=FinMq,K=FinMk,V=FinMv(2)

其中 M q ∈ R D f × D q , M k ∈ R D f × D k , M v ∈ R D f × D v M_q \in \mathbb{R}^{D_f \times D_q}, M_k \in \mathbb{R}^{D_f \times D_k}, M_v \in \mathbb{R}^{D_f \times D_v} MqRDf×Dq,MkRDf×Dk,MvRDf×Dv 是权重矩阵。它使用 Q Q Q K K K 之间的缩放点积来计算注意力权重,然后为每个查询聚合值:

A = softmax ( Q K T D k ) V (3) A = \text{softmax}\left(\frac{QK^T}{\sqrt{D_k}}\right)V \tag{3} A=softmax(Dk QKT)V(3)

最后,变换器使用非线性变换计算输出特征 F o u t F_{out} Fout,其形状与输入特征 F i n F_{in} Fin 相同。

F o u t = MLP ( A ) + F i n (4) F_{out} = \text{MLP}(A) + F_{in} \tag{4} Fout=MLP(A)+Fin(4)

变换器在架构中多次应用注意力机制,结果为 L L L 个注意力层。标准变换器的每个层都有多个并行注意力“头”,涉及为 F i n F_{in} Fin 生成多个 Q Q Q K K K V V V 值,并连接公式的结果值。与NLP中的标记输入结构不同,我们对网格结构的特征图进行操作。类似于先前在将变换器应用于图像的工作中,我们将每个模态的中间网格结构特征图视为一组而不是空间网格,并将该组的每个元素视为一个标记。图像和激光雷达BEV输入的卷积特征提取器在不同层编码场景的不同方面。因此,我们在编码器中不同尺度的整个过程中融合这些特征。让单一模态的中间网格结构特征图是一个维度为 H × W × C H \times W \times C H×W×C 的3D张量。对于 S S S 个不同模态,这些特征堆叠在一起形成一个维度为 ( S × H × W ) × C (S \times H \times W) \times C (S×H×W)×C 的序列。我们添加了一个可学习的位置嵌入,这是一个可训练的参数,其维度为 ( S × H × W ) × C (S \times H \times W) \times C (S×H×W)×C,以便网络可以在训练时推断不同标记之间的空间依赖性。我们还通过将标量值投影到 C C C 维向量来提供当前速度作为输入,使用线性层。输入序列、位置嵌入和速度嵌入通过元素-wise求和组合成一个维度为 ( S × H × W ) × C (S \times H \times W) \times C (S×H×W)×C 的张量。这个张量被馈送到变换器作为输入,它产生一个相同维度的输出。然后我们将输出重塑为 S S S 个特征图,每个维度为 H × W × C H \times W \times C H×W×C,并通过对现有特征图进行元素-wise求和来反馈到每个单独模态分支中。

3.4 航点预测网络

如图2所示,我们将512维特征向量通过一个MLP(包括2个隐藏层,分别为256和128个单元)来降低其维度为64,以提高计算效率,然后将其传递给使用GRUs实现的自回归航点网络。我们用64维特征向量初始化GRU的隐藏状态。GRU的更新门控制隐藏状态中编码的信息流向输出和下一个时间步。它还将当前位置和目标位置作为输入,这允许网络在预测下一个航点时专注于隐藏状态中相关的上下文。我们将目标位置的GPS坐标(注册到自车坐标系)作为输入提供给GRU,而不是编码器,因为它与预测的航点在同一BEV空间中,与它们相比,与以图像域表示目标位置的相关性更好。按照先前的工作,我们使用一个单层GRU,后面是一个线性层,它将隐藏状态作为输入,并预测自车当前坐标系中未来4个时间步的差分自车航点 { δ w t } t = 1 T \{\delta w_t\}_{t=1}^T {δwt}t=1T。因此,预测的未来航点由 { w t = w t − 1 + δ w t } t = 1 T \{w_t = w_{t-1} + \delta w_t\}_{t=1}^T {wt=wt1+δwt}t=1T 给出。第一个GRU单元的输入为 (0,0),因为BEV空间以自车的位置为中心。控制器:我们使用两个PID控制器分别进行横向和纵向控制,以从预测的航点 { w t } t = 1 T \{w_t\}_{t=1}^T {wt}t=1T 中获得转向、油门和制动值。纵向控制器接收连续时间步的航点向量之间的加权平均值的幅度,而横向控制器接收它们的取向。对于PID控制器,我们使用与先前工作相同的配置。实现细节可以在补充材料中找到。

3.5 损失函数

我们使用预测航点和地面真实航点(专家提供)之间的L1损失来训练网络,并将这些航点注册到当前坐标系。设 w g t t w_{gt_t} wgtt 代表时间步 t t t 的地面真实航点,则损失函数定义如下:

L = ∑ t = 1 T ∥ w t − w g t t ∥ 1 (5) L = \sum_{t=1}^{T} \|w_t - w_{gt_t}\|_1 \tag{5} L=t=1Twtwgtt1(5)

这里, w t w_t wt 表示预测的航点, w g t t w_{gt_t} wgtt 表示在训练时可用的地面真实航点。注意,地面真实航点 { w g t t } \{w_{gt_t}\} {wgtt} 与在训练和测试时都提供的稀疏目标位置 G G G 是不同的。

// A code block
   def train(self):
       self.model.train()

       num_batches = 0
       loss_epoch = 0.0
       detailed_losses_epoch  = {key: 0.0 for key in self.detailed_losses}
       self.cur_epoch += 1

       # Train loop
       for data in tqdm(self.dataloader_train):
           self.optimizer.zero_grad(set_to_none=True)
           losses = self.load_data_compute_loss(data)
           loss = torch.tensor(0.0).to(self.device, dtype=torch.float32)

           for key, value in losses.items():
               loss += self.detailed_weights[key] * value
               detailed_losses_epoch[key] += float(self.detailed_weights[key] * value.item())
           loss.backward()

           self.optimizer.step()
           num_batches += 1
           loss_epoch += float(loss.item())

       self.log_losses(loss_epoch, detailed_losses_epoch, num_batches, '')
     if ((self.args.backbone == 'transFuser') or (self.args.backbone == 'late_fusion') or (self.args.backbone == 'latentTF')):
        losses = self.model(rgb, lidar, ego_waypoint=ego_waypoint, target_point=target_point,
                       target_point_image=target_point_image,
                       ego_vel=ego_vel.reshape(-1, 1), bev=bev,
                       label=label, save_path=self.vis_save_path,
                       depth=depth, semantic=semantic, num_points=num_points)

model = LidarCenterNet(config, device, args.backbone, args.image_architecture, args.lidar_architecture, bool(args.use_velocity))

class LidarCenterNet(nn.Module):
    """
    Encoder network for LiDAR input list
    Args:
        in_channels: input channels
    """

    def __init__(self, config, device, backbone, image_architecture='resnet34', lidar_architecture='resnet18', use_velocity=True):
        super().__init__()
        self.device = device
        self.config = config
        self.pred_len = config.pred_len
        self.use_target_point_image = config.use_target_point_image
        self.gru_concat_target_point = config.gru_concat_target_point
        self.use_point_pillars = config.use_point_pillars

        if(self.use_point_pillars == True):
            self.point_pillar_net = PointPillarNet(config.num_input, config.num_features,
                                                   min_x = config.min_x, max_x = config.max_x,
                                                   min_y = config.min_y, max_y = config.max_y,
                                                   pixels_per_meter = int(config.pixels_per_meter),
                                                  )

        self.backbone = backbone


        if(backbone == 'transFuser'):
            self._model = TransfuserBackbone(config, image_architecture, lidar_architecture, use_velocity=use_velocity).to(self.device)
class TransfuserBackbone(nn.Module):
    """
    Multi-scale Fusion Transformer for image + LiDAR feature fusion
    image_architecture: Architecture used in the image branch. ResNet, RegNet and ConvNext are supported
    lidar_architecture: Architecture used in the lidar branch. ResNet, RegNet and ConvNext are supported
    use_velocity: Whether to use the velocity input in the transformer.
    """

    def __init__(self, config, image_architecture='resnet34', lidar_architecture='resnet18', use_velocity=True):
        super().__init__()
        self.config = config

        self.avgpool_img = nn.AdaptiveAvgPool2d((self.config.img_vert_anchors, self.config.img_horz_anchors))
        self.avgpool_lidar = nn.AdaptiveAvgPool2d((self.config.lidar_vert_anchors, self.config.lidar_horz_anchors))
        
        self.image_encoder = ImageCNN(architecture=image_architecture, normalize=True,
                                      out_features=self.config.perception_output_features)

        if(config.use_point_pillars == True):
            in_channels = config.num_features[-1]
        else:
            in_channels = 2 * config.lidar_seq_len

        if(self.config.use_target_point_image == True):
            in_channels += 1

        self.lidar_encoder = LidarEncoder(architecture=lidar_architecture, in_channels=in_channels,
                                          out_features=self.config.perception_output_features)

        self.transformer1 = GPT(n_embd=self.image_encoder.features.feature_info[1]['num_chs'],
                            n_head=config.n_head,
                            block_exp=config.block_exp,
                            n_layer=config.n_layer,
                            img_vert_anchors=config.img_vert_anchors,
                            img_horz_anchors=config.img_horz_anchors,
                            lidar_vert_anchors=config.lidar_vert_anchors,
                            lidar_horz_anchors=config.lidar_horz_anchors,
                            seq_len=config.seq_len,
                            embd_pdrop=config.embd_pdrop,
                            attn_pdrop=config.attn_pdrop,
                            resid_pdrop=config.resid_pdrop,
                            config=config, use_velocity=use_velocity)

        self.transformer2 = GPT(n_embd=self.image_encoder.features.feature_info[2]['num_chs'],
                            n_head=config.n_head,
                            block_exp=config.block_exp,
                            n_layer=config.n_layer,
                            img_vert_anchors=config.img_vert_anchors,
                            img_horz_anchors=config.img_horz_anchors,
                            lidar_vert_anchors=config.lidar_vert_anchors,
                            lidar_horz_anchors=config.lidar_horz_anchors,
                            seq_len=config.seq_len,
                            embd_pdrop=config.embd_pdrop,
                            attn_pdrop=config.attn_pdrop,
                            resid_pdrop=config.resid_pdrop,
                            config=config, use_velocity=use_velocity)
  • 这模型输入中为啥有语义这些信息呢,速度又是干嘛的

4 实验

在本节中,我们描述了我们的实验设置,并将我们的方法与几个基线进行了比较,进行了违规分析以研究不同的失败案例,并可视化了TransFuser的注意力图,并进行了消融研究以强调我们模型的不同组成部分的重要性。

任务:我们考虑在各种区域,如高速公路、城市地区和住宅区沿一组预定义路线进行导航的任务。路线由一系列稀疏的目标位置定义,由全局规划器提供,并对应于离散的导航命令,例如跟随车道、左右转弯、变道。我们的方法仅使用稀疏GPS位置进行驾驶。每条路线由几个场景组成,这些场景在预定义的位置初始化,测试代理处理不同类型对抗情况的能力,例如避障、在交叉口进行无保护转弯、车辆闯红灯,以及从遮挡区域突然出现的行人在随机位置过马路。代理需要在指定的时间限制内完成路线,同时遵循交通规则并应对高密度的动态代理。

数据集:我们使用CARLA模拟器进行训练和测试,特别是CARLA 0.9.10,它包括8个公开可用的城市。我们使用7个城市进行训练,并将Town05用于评估。对于生成训练数据,我们使用模拟中的特权信息设计了一个专家策略进行驾驶,并将数据以2FPS存储。我们选择Town05进行评估,因为它在可行驶区域的多样性方面与其他CARLA城市相比,例如多车道和单车道道路、高速公路和出口、桥梁和地下通道。我们考虑两种评估设置:Town05 Short:10条短路线,每条100-500米,每个包含3个交叉口;Town05 Long:10条长路线,每条1000-2000米,每个包含10个交叉口。每条路线都包含高密度的动态代理和对抗性场景,这些场景在路线的预定义位置生成。由于我们专注于处理动态代理和对抗性场景,我们将这方面的评估与天气条件的泛化分开,并且仅在ClearNoon天气下进行评估。

我们从三个指标报告结果:(1) 路线完成率(RC),完成的路线距离的百分比;(2) 驾驶得分(DS),这是路线完成率加权的违规乘数,该乘数考虑了与行人、车辆和静态元素的碰撞、路线偏差、车道违规、闯红灯和停车违规;(3) 违规计数。有关指标和违规的更多详细信息,请参见补充材料。

我们将我们的TransFuser模型与几个基线进行了比较:(1) CILRS[16]是一种条件模仿学习方法,代理学习从单个前向相机图像预测车辆控制,同时受导航命令的调节。我们紧密跟随作者提供的代码,并重新实现CILRS以适应CARLA 0.9.10,以解决与CARLA 0.8.4相比额外的导航命令。(2) LBC[8]是一种知识提炼方法,其中教师模型首先使用专家监督训练,以预测未来航点,然后是一个基于图像的学生模型,该模型使用来自教师的监督进行训练。它是CARLA 0.9.6上的最新最先进方法。我们使用作者提供的最新代码库在CARLA 0.9.10上进行训练,该代码库通过将不同视点作为通道堆叠来结合3个输入相机视图。(3) 自回归基于图像的航点预测(AIM):我们实现了我们的自回归航点预测网络,使用基于图像的ResNet-34编码器,它仅将前向相机图像作为输入。这个基线等同于将CILRS模型调整为在稀疏目标位置的条件下预测航点,而不是在导航命令的条件下预测车辆控制。用于此的图像编码器与CILRS和我们的模型相同。(4) 后期融合:我们实现了我们的架构的一个版本,其中图像和激光雷达特征是独立提取的,使用与TransFuser相同的编码器,但没有变换器(类似于[51]),然后通过元素求和融合并通过航点预测网络传递。(5) 几何融合:我们实现了一种多尺度基于几何的融合方法,受到[34, 33]的启发,涉及图像到激光雷达和激光雷达到图像特征融合。我们将每个0.125m × \times × 0.125m块在我们的激光雷达BEV表示中反投影到3D空间,从而产生一个3D体积。我们随机选择5个位于这个3D体积中的激光雷达点云中的点,并将它们投影到图像空间。我们通过元素求和聚合这些点的图像特征,然后将其传递给3层MLP。MLP的输出然后与相应0.125m × \times × 0.125m块的激光雷达BEV特征在多个分辨率处的特征提取器中组合。类似地,对于每个图像像素,我们从多个分辨率的激光雷达BEV特征中聚合信息。这个基线等同于用基于投影的特征融合替换我们架构中的变换器。我们也报告了用于生成我们训练数据的专家的结果,它定义了每个评估设置的性能上限。我们在补充材料中提供了有关所有基线的更多详细信息。

我们使用2个传感器模态,前向相机RGB图像和转换为BEV表示的激光雷达点云(第3.2节),即 S = 2 S=2 S=2。RGB图像使用在ImageNet上预训练的ResNet-34进行编码。激光雷达BEV表示使用从头开始训练的ResNet-18进行编码。在我们的默认TransFuser配置中,我们每个分辨率使用1个变换器和4个注意力头。我们为4个变换器选择 D q , D k , D v D_q, D_k, D_v Dq,Dk,Dv { 64 , 128 , 256 , 512 } \{64, 128, 256, 512\} {64,128,256,512} 中选择,对应于每个分辨率的特征嵌入维度 D f D_f Df。对于我们的每个基线,我们测试了不同的感知骨干,并选择了最好的:CILRS和AIM的ResNet-34,LBC的ResNet-50,每个传感器融合方法的图像编码器ResNet-34和激光雷达BEV编码器ResNet-18。更多详细信息可以在补充材料中找到。
在这里插入图片描述

4.1 结果

CILRS和LBC的性能:在我们的第一个实验中,我们检查当前基于图像的方法在CARLA上扩展到新的0.9.10评估设置的程度,该设置涉及复杂的多车道交叉口、对抗性场景和严厉的违规处罚。从表1a中的结果我们观察到CILRS在所有评估设置上的表现都很差。这并不奇怪,因为CILRS是受离散导航命令调节的,其数据分布是不平衡的,如补充材料所示。虽然原始的LBC[8]架构仅使用前向相机图像作为输入,但作者最近发布了他们架构的更新版本,有两个主要修改,(1) 多视图相机输入(前向、45°左侧和45°右侧),(2) 目标热图作为输入(而不是导航命令),这是通过将稀疏目标位置在图像空间中投影形成的。我们训练他们的更新模型并观察到LBC在短路线上的表现明显优于CILRS(表1a),这是预期的,因为它是使用使用真实BEV语义标签的教师模型进行训练的。然而,当在长路线上评估时,LBC的表现急剧下降,RC为32.09,但遭受多次违规,导致DS低至7.05。这是由于频繁的闯红灯和与车辆的碰撞(表1b)导致DS上的大的乘法处罚。这些结果表明CILRS和LBC无法处理城市驾驶的复杂性。

在这里插入图片描述
在这里插入图片描述

读后感
即时做的很差,也要开始做,没有实战,如何创新?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值