共计 4119 个字符,预计需要花费 11 分钟才能阅读完成。
背景与痛点
在自动驾驶系统的开发过程中,测试场景的构建是验证算法性能的关键环节。CARLA 作为开源的自动驾驶仿真平台,虽然功能强大,但手动构建测试场景存在几个明显痛点:

- 耗时费力 :每次测试都需要手动设置车辆、行人、天气等参数,重复操作多
- 场景一致性差 :人为操作难以保证多次测试的场景参数完全一致
- 复用性低 :构建好的场景难以保存和重复使用
- 复杂度高 :需要熟悉 CARLA API 的各种细节才能构建复杂场景
这些痛点严重影响了开发效率,特别是在需要大量不同场景进行回归测试时。
技术方案
整体框架设计
我们提出了一套基于 Python 的自动化场景构建方案,核心思路是:
- 使用描述文件定义场景参数
- 开发通用场景构建器解析描述文件
- 通过 CARLA Python API 实现场景的自动化生成
场景描述文件设计
采用 YAML 格式定义场景,因为它比 JSON 更易读且支持注释。一个典型场景描述文件包含以下模块:
scene:
name: urban_crossing
description: 城市十字路口行人横穿场景
environment:
weather:
precipitation: 0.8 # 降雨强度
cloudiness: 0.6
wetness: 0.7
sun_altitude: 45.0
actors:
ego_vehicle:
blueprint: vehicle.tesla.model3
spawn_point: {x: 120.4, y: 195.3, z: 0.5, yaw: 90.0}
pedestrians:
- blueprint: pedestrian.pedestrian_001
spawn_points:
- {x: 125.1, y: 192.8, z: 0.0}
waypoints:
- {x: 125.1, y: 200.5, z: 0.0}
npc_vehicles:
- blueprint: vehicle.audi.tt
spawn_point: {x: 130.2, y: 195.3, z: 0.5, yaw: 270.0}
speed: 30.0 # km/h
模块化组件设计
将场景元素拆分为可复用的模块:
- 环境模块 :处理天气、光照、时间等参数
- 车辆模块 :管理主车和 NPC 车辆的生成与控制
- 行人模块 :处理行人行为和路径规划
- 交通模块 :设置交通标志、信号灯等
每个模块都有对应的参数化接口,可以通过描述文件灵活配置。
核心实现
场景加载器实现
import yaml
import carla
class SceneLoader:
def __init__(self, client):
self.client = client
self.world = client.get_world()
self.blueprint_lib = self.world.get_blueprint_library()
def load_scene(self, scene_file):
with open(scene_file, 'r') as f:
scene_config = yaml.safe_load(f)
# 设置天气
self._set_weather(scene_config.get('environment', {}).get('weather', {}))
# 生成参与者
self._spawn_actors(scene_config.get('actors', {}))
def _set_weather(self, weather_params):
weather = carla.WeatherParameters(cloudiness=weather_params.get('cloudiness', 0.0),
precipitation=weather_params.get('precipitation', 0.0),
wetness=weather_params.get('wetness', 0.0),
sun_altitude_angle=weather_params.get('sun_altitude', 90.0)
)
self.world.set_weather(weather)
def _spawn_actors(self, actors_config):
# 生成主车
if 'ego_vehicle' in actors_config:
ego_cfg = actors_config['ego_vehicle']
bp = self.blueprint_lib.find(ego_cfg['blueprint'])
spawn_point = carla.Transform(carla.Location(**ego_cfg['spawn_point']),
carla.Rotation(yaw=ego_cfg['spawn_point']['yaw'])
)
self.ego = self.world.spawn_actor(bp, spawn_point)
# 生成 NPC 车辆
if 'npc_vehicles' in actors_config:
for npc_cfg in actors_config['npc_vehicles']:
self._spawn_npc_vehicle(npc_cfg)
# 生成行人
if 'pedestrians' in actors_config:
for ped_cfg in actors_config['pedestrians']:
self._spawn_pedestrian(ped_cfg)
交通流生成示例
def _spawn_npc_vehicle(self, npc_cfg):
bp = self.blueprint_lib.find(npc_cfg['blueprint'])
spawn_point = carla.Transform(carla.Location(**npc_cfg['spawn_point']),
carla.Rotation(yaw=npc_cfg['spawn_point']['yaw'])
)
vehicle = self.world.spawn_actor(bp, spawn_point)
# 设置自动驾驶行为
vehicle.set_autopilot(True)
# 设置目标速度
if 'speed' in npc_cfg:
speed = npc_cfg['speed'] / 3.6 # 转换为 m /s
control = carla.VehicleControl()
control.throttle = 1.0
vehicle.apply_control(control)
# 使用 PID 控制器保持速度
self._speed_controllers[vehicle.id] = PIDController(Kp=0.5, Ki=0.1, Kd=0.2, setpoint=speed)
性能考量
场景加载优化
- 预加载资源 :在初始化阶段批量加载常用蓝图
- 异步生成 :使用多线程生成大量 NPC
- LOD 控制 :根据距离调整细节级别
# 预加载常用蓝图
self._preload_blueprints = [
'vehicle.*',
'walker.pedestrian.*',
'sensor.*'
]
# 异步生成 NPC
from concurrent.futures import ThreadPoolExecutor
def batch_spawn_npcs(npc_configs):
with ThreadPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(self._spawn_npc_vehicle, cfg)
for cfg in npc_configs]
return [f.result() for f in futures]
内存管理
- 及时销毁 :测试完成后立即销毁 Actor
- 引用计数 :跟踪所有生成的 Actor
- 场景重置 :提供场景重置接口而非重新加载
def cleanup(self):
for actor in self.spawned_actors:
if actor.is_alive:
actor.destroy()
self.spawned_actors.clear()
避坑指南
常见问题与解决
- 坐标系统混淆
- 问题:CARLA 使用左手坐标系,容易与 ROS 等系统的右手系混淆
-
解决:明确转换关系,必要时封装坐标转换工具函数
-
异步操作问题
- 问题:传感器数据获取是异步的,直接读取可能得到空值
-
解决:使用回调机制或确保足够的等待时间
-
Actor 生命周期
- 问题:未正确销毁 Actor 会导致内存泄漏
- 解决:实现引用计数和自动清理机制
版本控制建议
- 对场景描述文件使用 Git 管理
- 为每个场景添加版本号
- 保存场景时记录 CARLA 引擎版本
metadata:
version: 1.0.2
carla_version: 0.9.13
created_at: 2023-05-15
总结与扩展
扩展自定义场景
- 继承基础 SceneLoader 类
- 实现自定义场景逻辑
- 注册新场景类型
class ConstructionZoneScene(SceneLoader):
def __init__(self, client):
super().__init__(client)
self.construction_props = []
def _setup_construction_zone(self, config):
# 添加路障、锥桶等
prop_bp = self.blueprint_lib.find('static.prop.constructioncone')
for loc in config['locations']:
prop = self.world.spawn_actor(prop_bp, carla.Location(**loc))
self.construction_props.append(prop)
实现特定场景的建议
以雨夜高速公路事故场景为例:
- 设置强降雨天气
- 放置故障车辆(双闪灯效果)
- 添加应急响应车辆
- 设置湿滑路面参数
- 调整能见度和光照条件
这套方案在我们的项目中已经验证,能够将场景构建时间从原来的 30 分钟缩短到 5 分钟以内,并且支持场景的版本管理和批量执行。希望本文能为你的自动驾驶测试工作带来帮助。
如果你对某个具体场景的实现有疑问,或者想分享你的改进方案,欢迎在评论区交流讨论。
正文完
