4. Python API入门

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

前面几章聊了CARLA的架构、传感器、地图这些概念,说白了都是在「看」。从这一章开始,我们要真正用代码去控制这个仿真世界。我个人觉得,Python API是CARLA最友好的入口——你不需要编译C++,不需要折腾复杂的依赖,一个pip install就能跑起来。

嗯,先给你吃颗定心丸:这一章的内容,你跟着敲一遍,半小时内就能跑通。

4.1 CARLA Python API 到底长什么样?

CARLA的Python API,说白了就是一组Python类和方法,封装了客户端和服务器之间的通信协议。你写的每一行Python代码,最终都会转成一条消息发给CARLA服务器,服务器执行完再给你返回结果。

我刚开始接触的时候,总觉得这玩意儿很神秘。后来拆开看了源码才发现,核心就几个类:

类名 作用 我常用的场景
carla.Client 连接CARLA服务器 创建客户端、设置超时
carla.World 代表仿真世界 获取地图、生成车辆、控制天气
carla.Actor 所有可移动/可交互对象的基类 车辆、行人、传感器都继承它
carla.BlueprintLibrary 蓝图库,存放所有可生成的对象模板 挑选车型、传感器型号
carla.Transform 位置+旋转 设置生成点、移动对象

你看,其实没几个类。记住这五个,你就能搞定80%的日常开发。

核心思路:Client → World → Actor,一条线串起来。先连服务器,再拿世界,最后操作对象。

4.2 连接服务器——别小看这一步

连接服务器,代码就两行:

import carla

client = carla.Client('localhost', 2000)
client.set_timeout(10.0)  # 设置超时,单位秒

但这里有个坑,我曾经踩过。

我曾经遇到过:客户端连上了,但一执行操作就报超时。查了半天,发现是服务器没开。CARLA服务器必须提前启动,客户端只是「敲门」,门没开当然进不去。

所以,连接之前请确认:

  • CARLA服务器已经启动(能看到那个UE4窗口)
  • 端口号一致(默认2000,你改了就用你的)
  • 超时时间别设太短(网络波动时5秒可能不够,我习惯设10秒)

连接成功后,你会得到一个client对象。这时候你可以试试:

print(client.get_client_version())
print(client.get_server_version())

如果两个版本号能对上,恭喜你,通信链路通了。

4.3 获取世界对象——你的仿真舞台

有了客户端,下一步就是获取世界对象。世界对象就是整个仿真环境的「总管」。

world = client.get_world()

就这么一行。但你知道吗?get_world()返回的是当前正在运行的世界。如果你加载了不同地图,世界对象也会变。

我个人习惯在获取世界后,先看一眼当前地图:

print(world.get_map().name)

这样能确认你确实在预期的地图里。我在项目里遇到过好几次,代码跑着跑着发现车在Town03,但我以为在Town05——嗯,那种感觉就像你开车导航错了城市。

世界对象能干的事太多了,我列几个最常用的:

  • world.get_actors() — 获取场景里所有对象
  • world.spawn_actor() — 生成一个新对象
  • world.get_weather() — 获取当前天气
  • world.set_weather() — 设置天气(下雨、大雾、夜晚)
  • world.tick() — 让仿真前进一步

小技巧:如果你需要反复获取世界对象,建议把它存成全局变量。每次调用get_world()其实都有开销,尤其是在高频率循环里。

4.4 基本对象操作——生成你的第一辆车

好了,重头戏来了。咱们来生成一辆车。

生成一个Actor需要三步:

  1. 从蓝图库里选一个模板
  2. 指定生成位置(Transform)
  3. 调用spawn_actor()

看代码:

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

# 2. 筛选出所有车辆蓝图
vehicle_bps = blueprint_library.filter('vehicle.*')

# 3. 选一辆车,比如奥迪
bp = vehicle_bps.find('vehicle.audi.a2')

# 4. 找一个生成点
spawn_points = world.get_map().get_spawn_points()
transform = spawn_points[0]

# 5. 生成车辆
vehicle = world.spawn_actor(bp, transform)

print(f'生成了车辆:{vehicle.type_id},位置:{transform.location}')

跑完这段,你应该能在CARLA窗口里看到一辆奥迪停在路上。

这里有几个细节我想强调一下:

  • 蓝图筛选:filter('vehicle.*')用的是通配符,你也可以精确到'vehicle.audi.*'
  • 生成点:每个地图都有预设的spawn_points,但数量有限。如果你要生成100辆车,可能不够用,需要自己算位置
  • 生成失败:如果位置被占了,spawn_actor会抛异常。我建议用try-except包一下

避坑指南:我曾经在循环里批量生成车辆,没做异常处理。结果第50辆车生成失败,整个程序崩了。从那以后,我生成Actor必加try-except。

4.5 对象操作——动起来

车生出来了,但它是静止的。怎么让它动?

两种方式:

  • 设置速度:vehicle.set_velocity()
  • 设置自动驾驶:vehicle.set_autopilot(True)

我个人更推荐先用自动驾驶模式测试,省心:

vehicle.set_autopilot(True)

就这么一行,车就会自己跑了。CARLA内置了一个简单的交通管理器,会控制车辆加速、刹车、转弯。

如果你想手动控制,可以这样:

import carla

# 创建一个速度向量(x向前,y向左,z向上)
velocity = carla.Vector3D(10.0, 0.0, 0.0)
vehicle.set_velocity(velocity)

但注意,set_velocity设置的是瞬时速度,不是持续加速。如果你想模拟油门控制,需要用vehicle.apply_control():

control = carla.VehicleControl()
control.throttle = 0.5  # 50%油门
control.steer = 0.0     # 方向盘回正
vehicle.apply_control(control)

嗯,这里要提醒你:apply_control需要每帧调用,否则车会停下来。所以一般放在游戏循环里。

4.6 清理工作——别忘了解放资源

仿真结束后,记得销毁生成的Actor。不然下次启动时,上一轮的车还停在路上。

vehicle.destroy()

如果你生成了很多Actor,可以批量销毁:

for actor in world.get_actors().filter('vehicle.*'):
    actor.destroy()

注意:销毁Actor后,这个对象就不能再用了。如果你还想用,得重新生成。我见过有人销毁后还去调用get_location(),直接报错。

4.7 本章知识体系

下面这张图,帮你把这一章的核心逻辑串起来:

Python API 核心流程 carla.Client 连接服务器 carla.World 获取世界对象 carla.Actor 操作对象 set_timeout() get_client_version() get_map() get_blueprint_library() spawn_actor() set_autopilot() apply_control() destroy() 记住这个流程:Client → World → Actor 所有操作都围绕这三步展开

你看,整个流程其实很清晰。先连服务器,再拿世界,最后操作对象。后面所有章节的内容,都是在这个框架上做加法。

我的建议:这一章的代码,你至少手敲三遍。第一遍照着抄,第二遍理解每行在干嘛,第三遍尝试改参数、换车型。三遍下来,Python API的基本功就扎实了。

好了,这一章就到这里。代码不多,但都是基础中的基础。你想想看,连服务器、拿世界、生成车、让车跑起来——这四个动作,几乎贯穿了所有CARLA仿真项目。后面不管你做传感器融合、路径规划还是强化学习,都离不开它们。

去试试吧,有问题随时翻回来看看。