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,就三步:
- 找到Blueprint
- 指定生成位置
- 调用
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)。
知识体系总览
说了这么多,我画了一张图帮你理清关系。你看一眼就懂了:
这张图你看懂了吗?World是老大,Map和Blueprint是它的左膀右臂,Actor是最终干活的小弟。传感器挂载就是"小弟带小弟"——车辆Actor带着传感器Actor一起跑。
避坑指南
最后分享几个我踩过的坑:
- 生成点不够用:有些地图的生成点就几十个,你一口气生成100辆车,后面的直接报错。我一般先
len(spawn_points)看一眼。 - 传感器没数据:检查一下是不是忘了设置
listen()回调。我刚开始就犯过这错,摄像头生成了,但啥也没录到。 - 坐标系搞反:挂载传感器时,Location的x、y、z别搞混。尤其是做多传感器标定时,差一厘米,数据就对不上。
好了,这一章的内容就到这儿。你把这些概念吃透了,后面的实操就会顺很多。