第4章:CARLA入门——架构、安装与基本API调用

说实话,我第一次接触CARLA的时候,也被它的架构吓了一跳。一个自动驾驶仿真器,怎么搞得跟个分布式系统似的?后来做项目做多了才明白——这种设计,恰恰是它最聪明的地方。

今天我们就来拆解一下CARLA。我会从架构讲起,然后带你完成安装,最后写几行代码让车跑起来。嗯,跟着我来,保证不迷路。

4.1 CARLA架构:客户端与服务器模式

CARLA的核心架构,说白了就是服务器+客户端的模式。你想想看,一个仿真环境里,谁负责渲染画面、计算物理、管理交通?谁又负责控制车辆、采集数据、做决策?

CARLA把这两件事分开了:

  • 服务器(Server):负责跑仿真世界。包括渲染、物理引擎、传感器模拟、交通管理。它就像一个游戏引擎,只管把世界跑起来。
  • 客户端(Client):负责控制。通过API向服务器发指令,比如“给我生成一辆车”、“让这辆车加速”、“读取摄像头画面”。

这种分离有什么好处?我举个例子。我在做多车协同项目时,需要同时控制十几辆车。如果所有逻辑都塞在服务器里,代码会乱成一锅粥。但用客户端-服务器模式,我可以开多个客户端,每个客户端控制几辆车,互不干扰。

核心理解:服务器是“世界”,客户端是“玩家”。一个世界可以有很多玩家,但每个玩家只能通过API跟世界交互。

下面这张图,是我自己画的架构示意图,帮你理清关系:

CARLA 服务器 渲染引擎 物理引擎 传感器模拟 交通管理器 世界状态 端口:2000 客户端 1 控制主车 + 摄像头 采集数据 客户端 2 控制NPC车辆 设置交通流 API API

你看,服务器在中间,多个客户端通过API跟它通信。每个客户端可以干不同的事——一个采集数据,一个控制交通,互不打架。

4.2 CARLA安装:两种方式,任你选择

安装CARLA,我个人推荐两种方式。你根据自己情况选:

方式一:从源码编译(推荐进阶用户)

这种方式最灵活,但耗时较长。我第一次编译的时候,等了将近两个小时。不过好处是你可以修改源码,甚至加自己的传感器模型。

# 克隆仓库
git clone https://github.com/carla-simulator/carla.git
cd carla

# 更新子模块
git submodule update --init --recursive

# 编译(Ubuntu系统)
make launch

注意:编译需要至少16GB内存,硬盘留出50GB空间。我曾经在8GB的笔记本上试过,编译到一半直接卡死。嗯,血的教训。

方式二:下载预编译包(推荐新手)

这是我最推荐新手的方式。去CARLA官网下载对应系统的压缩包,解压就能用。省心省力。

# 解压后,进入目录
cd CARLA_0.9.14

# 启动服务器
./CarlaUE4.sh

启动后你会看到一个窗口,里面是CARLA的默认小镇。如果窗口一闪而过,检查一下显卡驱动。我遇到过好几次这种问题,基本都是驱动版本不对。

4.3 基本API调用:让车动起来

服务器跑起来了,接下来我们用Python客户端跟它对话。先装依赖:

pip install carla

然后写个最简单的脚本:

import carla
import random

# 连接服务器
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)

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

# 获取蓝图库(所有可生成的模型)
blueprint_library = world.get_blueprint_library()

# 选一辆车
vehicle_bp = blueprint_library.filter('model3')[0]

# 找个出生点
spawn_points = world.get_map().get_spawn_points()
spawn_point = random.choice(spawn_points)

# 生成车辆
vehicle = world.spawn_actor(vehicle_bp, spawn_point)

# 让车动起来
vehicle.apply_control(carla.VehicleControl(
    throttle=0.5,  # 油门
    steer=0.0,     # 方向盘
    brake=0.0      # 刹车
))

print("车辆已生成,正在行驶...")

这段代码干了什么?

  1. 连接本地2000端口的CARLA服务器
  2. 从蓝图库里选了一辆特斯拉Model 3
  3. 在地图上随机找了个位置生成
  4. 给了个50%的油门,车就往前跑了

小技巧:如果你看不到车动,检查一下服务器窗口是不是被最小化了。CARLA默认是“无物理”模式?不,默认是有物理的。但如果你用了synchronous_mode,就需要手动推进仿真时间。这个我们后面会细讲。

4.4 客户端与服务器模式详解

刚才我们写了个最简单的客户端。但实际项目中,你可能会遇到几个关键问题:

4.4.1 同步模式 vs 异步模式

这是新手最容易踩的坑。我刚开始做的时候,也搞混过。

模式 说明 适用场景
异步模式(默认) 服务器自己跑自己的,客户端只管发指令 简单测试、可视化演示
同步模式 客户端控制仿真步进,服务器等客户端指令才更新 强化学习、数据采集、需要精确时序的场景

同步模式的代码长这样:

# 设置为同步模式
settings = world.get_settings()
settings.synchronous_mode = True
world.apply_settings(settings)

# 每步手动推进
while True:
    # 让服务器更新一帧
    world.tick()
    
    # 读取传感器数据
    # 控制车辆
    # ...

为什么要用同步模式?举个例子。你在采集训练数据时,需要保证每帧都采集到传感器数据。如果用异步模式,服务器可能在你还没读完数据时就更新了下一帧,导致数据错乱。同步模式就能保证“你一步,我一步”。

4.4.2 多客户端连接

CARLA支持多个客户端同时连接同一个服务器。每个客户端可以控制不同的角色。我在做V2X仿真时,就开了三个客户端:一个控制主车,一个控制路侧单元,一个控制其他交通参与者。

# 客户端A:控制主车
client_a = carla.Client('localhost', 2000)
world_a = client_a.get_world()
# ... 生成主车,控制逻辑

# 客户端B:控制NPC
client_b = carla.Client('localhost', 2000)
world_b = client_b.get_world()
# ... 生成NPC,设置自动驾驶

关键点:多个客户端共享同一个世界状态。你在客户端A生成的车,客户端B也能看到。但每个客户端只能控制自己生成的Actor。

4.5 避坑指南

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

  • 端口被占用:如果启动服务器时提示端口被占用,用lsof -i :2000查一下谁在用。我遇到过好几次是之前没关干净的CARLA进程。
  • 版本不匹配:客户端和服务器版本必须一致。我曾经用0.9.13的客户端连0.9.14的服务器,API调用直接报错。
  • 显卡驱动:CARLA对NVIDIA显卡支持最好。AMD显卡也能用,但性能会差一些。如果你用集成显卡,嗯...建议换个电脑。
  • Python版本:推荐Python 3.8或3.9。3.10以上有些依赖包还没适配。

好了,这一章的内容就到这里。你现在应该能理解CARLA的架构,能启动服务器,能用Python让一辆车跑起来了。下一章我们会深入传感器——摄像头、激光雷达、毫米波雷达,看看怎么用它们采集真实数据。


可可精品资料库