4. CARLA基础入门
说实话,刚接触CARLA那会儿,我也挺懵的。一个自动驾驶仿真器,怎么还分客户端和服务器?世界模型又是什么鬼?别急,这一章咱们就把这些概念掰开揉碎了讲清楚。
4.1 CARLA世界模型:你就是在搭建一个虚拟世界
CARLA的世界模型,说白了就是一个虚拟的沙盒。你可以在里面放道路、放建筑、放车辆、放行人,甚至控制天气和时间。
我个人习惯把这个世界模型想象成一个大舞台:
- 地图(Map):舞台的布景,包括道路、车道线、红绿灯、路标。
- 参与者(Actor):舞台上的演员,包括车辆、行人、传感器。
- 天气(Weather):舞台的灯光和特效,晴天、雨天、雾天随便调。
- 蓝图(Blueprint):演员的“出生证明”,定义了车辆型号、颜色、传感器配置。
我在项目中遇到过一个问题:明明加载了地图,但车辆就是不动。后来发现,是我忘了把车辆“生成”到世界里。你想想看,舞台搭好了,演员没上场,戏怎么演?
World对象,它管理着地图、参与者列表、天气设置和帧率。所有操作都围绕这个对象展开。
4.2 客户端与服务器架构:谁在干活?
CARLA采用的是客户端-服务器(C/S)架构。这个设计很有意思,我刚开始也觉得多此一举,后来才发现它有多香。
简单来说:
- 服务器(Server):负责渲染画面、物理计算、传感器数据生成。它是个“闷头干活的壮汉”。
- 客户端(Client):负责发送指令、接收数据、控制逻辑。它是个“发号施令的指挥官”。
为什么会这样设计?因为仿真计算量很大,尤其是多车协同、传感器融合的场景。把渲染和逻辑分开,你就可以在一台高性能机器上跑服务器,在另一台机器上跑客户端,甚至多个客户端同时连接一个服务器。
下面这张图,是我自己画的一个架构流程图,帮你理清关系:
4.3 基本API调用:让车跑起来
好了,理论说完了,咱们直接上代码。我习惯先连上服务器,再一步步操作。
4.3.1 连接服务器与加载世界
import carla
# 连接服务器,默认端口2000
client = carla.Client('localhost', 2000)
client.set_timeout(10.0) # 设置超时,防止卡死
# 获取世界对象
world = client.get_world()
# 或者加载指定地图
# world = client.load_world('Town03')
嗯,这里要注意:set_timeout一定要设。我第一次写的时候没设,结果网络一波动,脚本直接卡死,连错误提示都没有。
4.3.2 生成一辆车
生成车辆需要三步:获取蓝图、选择生成点、生成。
# 1. 获取蓝图库
blueprint_library = world.get_blueprint_library()
# 2. 选择一辆车(我习惯用特斯拉Model 3)
vehicle_bp = blueprint_library.find('vehicle.tesla.model3')
# 3. 获取一个随机生成点
spawn_points = world.get_map().get_spawn_points()
spawn_point = spawn_points[0] # 选第一个点
# 4. 生成车辆
vehicle = world.spawn_actor(vehicle_bp, spawn_point)
spawn_actor会报错。我建议用try_spawn_actor,它返回None而不是抛异常,更安全。
4.3.3 控制车辆移动
控制车辆有两种方式:直接控制(手动挡)和自动驾驶(自动挡)。
方式一:手动控制
# 创建一个控制对象
control = carla.VehicleControl()
control.throttle = 0.5 # 油门,0-1
control.steer = 0.0 # 转向,-1到1
control.brake = 0.0 # 刹车,0-1
# 应用控制
vehicle.apply_control(control)
方式二:开启自动驾驶
# 让CARLA内置的AI驾驶
vehicle.set_autopilot(True)
我个人更推荐先用手动控制调试逻辑,等稳定了再开自动驾驶。你想想看,如果连油门刹车都控制不好,直接上自动驾驶,出了问题你都不知道是代码的锅还是AI的锅。
4.3.4 完整示例:生成一辆车并让它跑起来
import carla
import time
# 连接服务器
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)
world = client.get_world()
# 生成车辆
bp = world.get_blueprint_library().find('vehicle.tesla.model3')
spawn_point = world.get_map().get_spawn_points()[0]
vehicle = world.spawn_actor(bp, spawn_point)
# 手动控制:先加速,再转弯
control = carla.VehicleControl()
control.throttle = 0.6
vehicle.apply_control(control)
time.sleep(3) # 直行3秒
control.steer = 0.3 # 右转
vehicle.apply_control(control)
time.sleep(2)
# 清理
vehicle.destroy()
destroy(),否则服务器里会残留一堆“幽灵车”,拖慢仿真速度。我刚开始经常忘,结果仿真越来越卡,还以为是电脑不行。
4.4 常用API速查表
| 功能 | API | 说明 |
|---|---|---|
| 连接服务器 | carla.Client(host, port) |
默认端口2000 |
| 获取世界 | client.get_world() |
获取当前世界 |
| 加载地图 | client.load_world('Town01') |
切换地图 |
| 获取蓝图 | world.get_blueprint_library() |
获取所有可生成对象 |
| 生成参与者 | world.spawn_actor(blueprint, transform) |
返回Actor对象 |
| 安全生成 | world.try_spawn_actor(blueprint, transform) |
失败返回None |
| 应用控制 | vehicle.apply_control(control) |
传入VehicleControl |
| 自动驾驶 | vehicle.set_autopilot(True) |
内置AI驾驶 |
| 销毁参与者 | actor.destroy() |
必须调用,释放资源 |
这一章的内容其实不难,核心就是理解世界模型、C/S架构、API调用这三板斧。你只要把代码敲一遍,跑通了,后面的事情就顺了。我当年也是从这行代码开始的:vehicle.apply_control(control)。看着屏幕上的车真的动起来,那种感觉,嗯,挺爽的。