2、Carla基础环境搭建:Ubuntu系统配置、Carla源码编译与安装、Carla Python API入门、Carla客户端与服务端通信

好,咱们正式开始动手了。

这一章,说白了就是要把Carla这个仿真环境给「支棱」起来。我见过不少同学,一上来就急着跑代码,结果环境没配好,折腾一整天连个车都看不到。嗯,咱们别走那个弯路。

2.1 Ubuntu系统配置——先把地基打牢

Carla官方推荐的是Ubuntu 18.04或20.04。我个人习惯用20.04,因为驱动支持和软件包更新都比较舒服。你想想看,如果系统版本太老,显卡驱动装不上,那后面全是坑。

第一步:更新系统包

拿到一台新机器,第一件事就是更新。别偷懒,我见过有人跳过这步,结果编译到一半报缺库,回头再补更麻烦。

sudo apt update
sudo apt upgrade -y
sudo apt install build-essential cmake git python3-dev python3-pip -y

第二步:显卡驱动与CUDA

Carla的渲染依赖GPU。如果你用的是N卡,记得装驱动。我曾经在一台笔记本上折腾了三个小时,最后发现是驱动版本太低,Carla直接黑屏。

注意: 不要用Ubuntu自带的nouveau开源驱动,性能差且不稳定。建议去NVIDIA官网下载.run文件手动安装,或者用ppa源。
# 查看显卡型号
lspci | grep -i nvidia

# 安装推荐驱动(以460版本为例)
sudo apt install nvidia-driver-460

装完驱动记得重启,然后跑一下 nvidia-smi 确认驱动生效。

第三步:安装依赖库

Carla的依赖还挺多的。我整理了一个清单,你直接复制粘贴就行:

sudo apt install libpng16-dev libjpeg-dev libtiff5-dev libjasper-dev
sudo apt install libboost-all-dev libeigen3-dev libgflags-dev libgoogle-glog-dev
sudo apt install libprotobuf-dev protobuf-compiler
sudo apt install libhdf5-dev libhdf5-serial-dev
小技巧: 如果你网络不好,可以换国内源(比如清华源、阿里源),下载速度能快好几倍。

2.2 Carla源码编译与安装——自己动手,丰衣足食

说实话,Carla官方提供了预编译包,直接下载解压就能用。但我为什么还推荐你走一遍源码编译?因为后面你要集成Autoware,免不了要改Carla的底层代码。你想想看,到时候连编译流程都不熟,怎么改?

第一步:克隆源码

git clone https://github.com/carla-simulator/carla.git
cd carla
git checkout master  # 或者指定版本,比如0.9.13

第二步:编译Carla

Carla的编译脚本是用Python写的。我第一次编译的时候,等了将近两个小时。嗯,别急,泡杯咖啡慢慢等。

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

# 开始编译
make PythonAPI
make launch

这里有个坑:make PythonAPI 会生成Python的API包,而 make launch 会编译Carla服务端。如果你只需要Python接口,可以只跑第一个。

重要: 编译过程中如果报错,多半是缺依赖。别慌,看报错信息,缺什么装什么。我遇到过缺 libomp-dev 的情况,装完重新编译就好了。

第三步:验证安装

编译完成后,在 PythonAPI/carla/dist/ 目录下会生成一个 .egg 文件。这就是Carla的Python包。你可以把它加到环境变量里:

export PYTHONPATH=$PYTHONPATH:/path/to/carla/PythonAPI/carla/dist/carla-0.9.13-py3.7-linux-x86_64.egg

然后跑一个简单的测试脚本:

import carla
print(carla.__version__)

如果能打印出版本号,恭喜你,环境搭好了。

2.3 Carla Python API入门——从Hello World到控制车辆

Carla的Python API设计得挺优雅的。说白了,就是通过客户端去连接服务端,然后操作世界里的各种对象。

2.3.1 连接服务端

import carla

# 创建客户端,连接本地服务端
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)

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

这里要注意,端口2000是Carla的默认端口。如果你在同一台机器上跑多个实例,记得改端口。

2.3.2 生成车辆

# 获取蓝图库
blueprint_library = world.get_blueprint_library()

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

# 选择一个生成点
spawn_points = world.get_map().get_spawn_points()
spawn_point = spawn_points[0]

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

我在项目中遇到过一个问题:有时候生成点被占用了,会报错。所以最好加个try-except,或者先检查一下。

2.3.3 控制车辆

# 创建一个控制命令
control = carla.VehicleControl()
control.throttle = 0.5  # 油门
control.steer = 0.0     # 转向
control.brake = 0.0     # 刹车

# 应用控制
vehicle.apply_control(control)

你想想看,这其实就是模拟器里的「油门刹车方向盘」。后面集成Autoware的时候,我们就是通过这种方式把规划好的控制指令发过去。

提示: Carla的坐标系是左手系,X轴向前,Y轴向右,Z轴向上。和ROS的坐标系不太一样,后面做坐标转换的时候要小心。

2.4 Carla客户端与服务端通信——搞清楚谁在说话

Carla采用的是客户端-服务端架构。服务端负责渲染和物理模拟,客户端负责发送指令和接收数据。说白了,服务端是「演员」,客户端是「导演」。

通信流程

  1. 客户端通过TCP连接到服务端(默认端口2000)
  2. 客户端发送请求(比如生成车辆、设置天气)
  3. 服务端处理请求,返回结果
  4. 客户端通过传感器获取数据(比如摄像头图像、激光雷达点云)

传感器数据流

Carla的传感器数据是通过回调函数传递的。举个例子:

# 添加一个摄像头
camera_bp = blueprint_library.find('sensor.camera.rgb')
camera = world.spawn_actor(camera_bp, carla.Transform(carla.Location(x=1.5, z=2.4)), attach_to=vehicle)

# 定义回调函数
def process_image(image):
    # image是carla.Image对象
    array = np.frombuffer(image.raw_data, dtype=np.uint8)
    array = array.reshape((image.height, image.width, 4))
    # 这里可以保存图像或者做推理

# 监听数据
camera.listen(lambda data: process_image(data))
注意: 传感器数据是异步的。如果你在主线程里做耗时操作,可能会丢帧。建议用多线程或者队列来处理。

同步模式 vs 异步模式

Carla默认是异步模式,服务端自己跑自己的。但如果你要做仿真测试,建议用同步模式,这样每一步都是可控的。

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

# 手动推进仿真
world.tick()

我曾经在做一个多车协同的项目时,就是因为没开同步模式,导致两辆车的时间戳对不上,数据全乱了。嗯,从那以后我只要做测试,必开同步模式。

小结

这一章的内容,说白了就是三件事:装系统、编译Carla、学会用Python API。你可能会觉得编译过程有点繁琐,但相信我,这一步走扎实了,后面集成Autoware的时候会顺畅很多。

下一章,咱们开始搞Autoware的安装和配置。到时候你会发现,Carla和Autoware的通信才是真正的重头戏。