2. CARLA基础架构与核心概念

说实话,刚接触CARLA的时候,我也被它那一堆概念搞得有点懵。什么World、Map、Blueprint、Actor……听着就像在学一门新语言。但别急,这些东西其实没那么玄乎。我带你捋一遍,你就明白了。

一句话总结:CARLA的世界里,World是舞台,Map是舞台布景,Blueprint是演员的剧本,Actor就是上台表演的演员本人。

世界(World)—— 一切开始的地方

World在CARLA里是最顶层的对象。你可以把它理解成整个仿真环境的"大管家"。它管着天气、时间、还有所有参与者的生命周期。

我刚开始写代码时,第一件事就是创建World对象。没有它,啥也干不了。

# 获取世界对象
world = client.get_world()

# 或者换个地图
world = client.load_world('Town03')

World能干的事还挺多的。比如控制天气、获取当前帧数、设置步进模式等等。我个人习惯在调试时把同步模式打开,这样每一帧都由我来控制,不会出现"车都撞上了,传感器还没反应过来"的尴尬。

小技巧:用 world.get_settings() 和 world.apply_settings() 可以精细控制仿真步进。这在回放数据时特别有用。

地图(Map)—— 你脚下的路

Map就是World里的"地形图"。它包含了道路、车道线、红绿灯、路标等等。CARLA自带了好几个城镇地图,从Town01到Town12,各有各的风格。

我记得有一次做高速公路场景测试,Town03的环形立交让我折腾了好久。后来我干脆换成了Town05,直线多、弯道少,调试起来舒服多了。

# 获取当前地图
current_map = world.get_map()

# 获取地图中的生成点
spawn_points = current_map.get_spawn_points()

Map里有个很重要的东西叫Waypoint(路径点)。它把道路切成了一段段的小点,每个点都带着方向、车道信息。做路径规划时,这东西就是你的"导航线"。

蓝图(Blueprint)—— 造车的图纸

Blueprint是什么?说白了就是"造什么东西的说明书"。你要造一辆车、一个行人、一个摄像头,都得先找到对应的Blueprint。

CARLA的Blueprint库里啥都有。轿车、卡车、摩托车、行人、甚至自行车……还有各种传感器:摄像头、激光雷达、GPS、IMU。

# 获取所有可用的蓝图
blueprint_library = world.get_blueprint_library()

# 找一辆车
vehicle_bp = blueprint_library.find('vehicle.tesla.model3')

# 找一个摄像头
camera_bp = blueprint_library.find('sensor.camera.rgb')

Blueprint还可以设置属性。比如摄像头的分辨率、视场角,激光雷达的线数、探测距离。这些参数直接影响你的数据质量。

注意:不是所有Blueprint都能随便用。有些车辆模型在特定地图上可能没有合适的生成点。我曾经遇到过"车生成了,但卡在地里"的情况……嗯,后来我学乖了,生成前先检查一下 map.get_spawn_points() 够不够用。

参与者(Actor)—— 舞台上的演员

Actor就是所有能在仿真世界里动的东西。车、人、传感器、交通标志……统统都是Actor。它们有生命周期:生成、移动、销毁。

你想想看,一辆车从Blueprint变成真正的Actor,就三步:

  1. 找到Blueprint
  2. 指定生成位置
  3. 调用 spawn_actor()
# 生成一辆车
transform = spawn_points[0]
vehicle = world.spawn_actor(vehicle_bp, transform)

# 生成一个摄像头并挂载到车上
camera = world.spawn_actor(camera_bp, camera_transform, attach_to=vehicle)

这里有个关键点:传感器也是Actor。它们可以挂载到其他Actor上,跟着一起移动。这就是我们做数据采集的基础。

坐标系与传感器挂载原理

说到挂载,就不得不提坐标系。CARLA用的是左手坐标系,跟Unreal Engine保持一致。简单记:

  • X轴:向前(车头方向)
  • Y轴:向右
  • Z轴:向上

传感器挂载时,你需要指定一个相对位置和旋转。比如把摄像头装在车顶:

camera_transform = carla.Transform(
    carla.Location(x=0.0, z=2.5),  # 车顶位置
    carla.Rotation(pitch=-15)       # 稍微向下俯视
)

我刚开始做多传感器融合时,犯过一个低级错误:激光雷达和摄像头的坐标系没对齐,导致点云投影到图像上全是偏移的。后来我画了一张坐标系对照表,每次挂载前都核对一遍,再也没出过问题。

核心要点:传感器挂载的本质就是"父子关系"。父Actor移动,子传感器跟着动。你只需要定义好子相对于父的偏移量(Location + Rotation)。

知识体系总览

说了这么多,我画了一张图帮你理清关系。你看一眼就懂了:

CARLA 核心架构关系图 World(世界) Map(地图) 道路 · 车道线 · 红绿灯 生成点 · Waypoint Blueprint(蓝图) 车辆 · 行人 · 传感器 属性配置 · 参数设置 Actor(参与者) 车辆 · 行人 · 传感器 生命周期:生成 → 移动 → 销毁 属于 实例化 管理 传感器作为子Actor挂载到车辆上,通过相对Transform定义位置与朝向

这张图你看懂了吗?World是老大,Map和Blueprint是它的左膀右臂,Actor是最终干活的小弟。传感器挂载就是"小弟带小弟"——车辆Actor带着传感器Actor一起跑。

避坑指南

最后分享几个我踩过的坑:

  • 生成点不够用:有些地图的生成点就几十个,你一口气生成100辆车,后面的直接报错。我一般先 len(spawn_points) 看一眼。
  • 传感器没数据:检查一下是不是忘了设置 listen() 回调。我刚开始就犯过这错,摄像头生成了,但啥也没录到。
  • 坐标系搞反:挂载传感器时,Location的x、y、z别搞混。尤其是做多传感器标定时,差一厘米,数据就对不上。

好了,这一章的内容就到这儿。你把这些概念吃透了,后面的实操就会顺很多。