前言
“浅析”究竟有多浅——本文将围绕三个自动驾驶端到端模型闭环仿真测试项目的例子,分析不同的端到端模型仿真框架。主要分析的内容是:仿真系统产生的传感器数据是如何传递给端到端模型的,模型输出的控制命令又是如何反馈给仿真系统的。
本文的三个例子正好覆盖了基于游戏引擎的仿真系统、基于3DGS三维重建的仿真系统和基于生成式模型的仿真系统。
Bench2Drive
-
Website: https://thinklab-sjtu.github.io/Bench2Drive/
-
Github: https://github.com/Thinklab-SJTU/Bench2Drive/
Bench2Drive项目的详细介绍,可以参考自动驾驶之心的文章:
上交ReThinkLab新作 | Bench2Drive:首个端到端自动驾驶综合能力闭环评估开放平台!
简言之,Bench2Drive是一个以开源自动驾驶仿真软件CARLA为基础的测试框架,而且重新实现了UniAD,VAD等方法的代码。我们将以此项目的代码为例分析CARLA的Leaderboard,一个常用的端到端仿真测试框架。
Bench2Drive闭环仿真程序总入口:Bench2Drive/leaderboard/leaderboard/leaderboard_evaluator.py:main(),其中主要创建了一个LeaderboardEvaluator的类的实例并调用了其run()方法。
LeaderboardEvaluator类主要职责包括管理CARLA服务器生命周期、加载路线配置和城镇环境、动态加载智能体模块、验证传感器配置有效性等。
核心组件:
-
_setup_simulation()
: Bootstraps CARLA server/client with retry logic
-
_load_and_run_scenario()
: Core scenario loop with error handling
-
run()
: Main execution flow with route iteration
-
_cleanup()
: Ensures proper resource teardown
在创建LeaderboardEvaluator类实例的时候,在该类的构造函数中:
-
self.module_agent将从leaderboard/team_code/下获取被测端到端模型的python module,例如来自Bench2DriveZoo仓库的uniad_b2d_agent.py
-
会创建一个ScenarioManager类的实例self.manager。
接下来,在LeaderboardEvaluator的run()方法会调用
def _load_and_run_scenario()
,在该方法中:
-
self.agent_instance会创建一个UniAD的UniadAgent类的实例,UniadAgent类继承自leaderboard/leaderboard/autoagents/autonomous_agent.py中的AutonomousAgent类。AutonomousAgent类在初始化时会给自己创建一个来自leaderboard/leaderboard/envs/sensor_interface.py的SensorInterface()的实例:
self.sensor_interface = SensorInterface()
-
self.manager.load_scenario(self.route_scenario, self.agent_instance, config.index, config.repetition_index)
进入ScenarioManager类的load_scenario()方法
在self.manager.load_scenario()方法中:
-
self._agent_wrapper = AgentWrapperFactory.get_wrapper(agent)
给agent(即上一步的agent_instance)实例选择一个AgentWrapper,对于本文中的UniAD,这将会是实例化一个leaderboard/leaderboard/autoagents/agent_wrapper.py的AgentWrapper类。
-
self._agent_wrapper.setup_sensors(self.ego_vehicles[0])
执行AgentWrapper类的setup_sensors方法,在carla中的主车上附加上仿真所用的传感器。
在setup_sensors()方法的代码内部,有使用CARLA仿真经验的人就会发现一个熟悉的语句:
sensor.listen(CallBack(id_, type_, sensor, self._agent.sensor_interface))
,这里的
self._agent
就是前文的agent_instance。
其中,CallBack类也来自于leaderboard/leaderboard/envs/sensor_interface.py,该类的__call__方法会将CARLA仿真的传感器数据存入agent的sensor_interface中的data_buffers的Queue()队列中。因此,在仿真运行过程中,每一步的传感器数据就会通过这个callback存入UniadAgent类的实例的sensor_interface中。
我们再回到
def _load_and_run_scenario()
方法,接下来会进入
self.manager.run_scenario()
,run_scenario()的核心是ScenarioManager类的
def _tick_scenario(self)
方法: 其中的
ego_action = self._agent_wrapper()
,AgentWrapper的__call__方法会直接返回UniadAgent类的实例,调用该类的__call__方法。
在UniadAgent类的父类AutonomousAgent类的__call__方法中,首先就获取了该步仿真下的传感器数据:
input_data = self.sensor_interface.get_data(GameTime.get_frame())
get_data会把数据从sensor_interface的data_buffers中取出。
control = self.run_step(input_data, timestamp)
UniadAgent类覆写的run_setup会被调用。就像Leaderboard官方文档给出的agent编写建议
creating-your-own-autonomous-agent
写的那样,这个函数的输入input_data就包含了一个端到端模型所需要的传感器数据输入。
在UniadAgent类实例的run_setup中,传感器输入经过处理,最终会输入给UniAD模型进行推理:
output_data_batch = self.model(input_data_batch, return_loss=False, rescale=True)
,而推理结果经过一些列的PID调制等步骤,最终会作为control输出。
我们再回到
def _tick_scenario(self)
方法,上文提到的
ego_action = self._agent_wrapper()
,ego_action承接了UniAD模型输出的control,并接下来通过
self.ego_vehicles[0].apply_control(ego_action)
控制仿真中的主车。
至此,我们通过Bench2Drive项目简要分析了CARLA Leaderboard在端到端模型闭环仿真中的输入输出形式。
HUGSIM
-
Github: https://github.com/hyzhou404/HUGSIM/
HUGSIM项目的详细介绍,可以参考自动驾驶之心的文章:
真实闭环拉满!浙大&华为发布全新闭环仿真工具HUGSIM
简言之,HUGSIM不仅研究了一种新的基于3DGS的自动驾驶场景三维重建方法,而且在该方法的基础上开发了一个可闭环测试端到端自动驾驶模型的仿真系统。
HUGSIM使用Gymnasium作为框架,以完成仿真运行。Gymnasium是一个强化学习环境库,它提供了一套标准化的接口来构建和测试强化学习算法。以下是一些基本用法,重点介绍
gymnasium.make()
,
gymnasium.reset()
,
gymnasium.step()
等方法的使用:
1. 创建环境
gymnasium.make()
gymnasium.make()
函数用于创建或加载一个环境。你需要传入环境的ID,例如 "CartPole-v1"。
2. 重置环境
gymnasium.reset()
gymnasium.reset()
方法用于重置环境到初始状态。在每次新的episode开始时,都需要调用这个方法。它返回环境的初始观察值。
3. 与环境交互
gymnasium.step()
gymnasium.step(action)
方法用于执行一个动作,并返回环境的反馈。具体返回值包括:
-
-
-
terminated
:布尔值,表示环境是否终止(例如,杆倒下或达到最大步数)。
-
truncated
:布尔值,表示环境是否被截断(例如,达到最大步数)。
-