3、Python API入门:安装carla Python库、导入模块、连接客户端、获取世界对象、获取蓝图库、生成车辆与行人
好,咱们正式开始动手了。
前面两章我们把Carla的架构和地图聊了一遍,算是热身。这一章,才是真正进入编程环节。说白了,就是让你学会怎么用Python跟Carla仿真器“对话”。
我个人习惯,学一个新工具,第一件事就是先把它的API跑通。哪怕只是生成一辆车停在路边,也比看十遍文档强。你想想看,代码跑起来的那一刻,那种掌控感,才是学习的动力。
3.1 安装carla Python库
这一步其实很简单,但坑也不少。我记得我第一次装的时候,直接用了pip install carla,结果装了个不知道什么版本的包,跟我的仿真器版本对不上,折腾了半天。
正确做法是:用Carla安装包自带的Python库。
你下载完Carla的压缩包,解压后,在 PythonAPI/carla/dist/ 目录下,就能找到一个 .whl 文件。比如我用的0.9.14版本,文件名是 carla-0.9.14-cp39-cp39-win_amd64.whl。
然后打开终端,用pip安装它:
pip install carla-0.9.14-cp39-cp39-win_amd64.whl
装完之后,在Python里试试:
import carla
print(carla.__version__)
如果能正常输出版本号,恭喜你,第一步走通了。
3.2 导入模块与连接客户端
库装好了,接下来就是写脚本。我一般会先建一个 main.py 文件,然后开始写。
首先,导入必要的模块:
import carla
import random
import time
carla 是核心库,random 和 time 是Python自带的,后面生成随机车辆和等待时会用到。
然后,连接客户端。Carla仿真器启动后,默认会在本地 localhost:2000 端口监听。我们只需要创建一个客户端对象:
client = carla.Client('localhost', 2000)
client.set_timeout(10.0) # 设置超时时间,单位秒
这里有个小细节:set_timeout 一定要设。如果不设,网络一波动,脚本就会卡死在那。我刚开始写的时候没设,有一次仿真器卡住了,我的脚本也一直挂在那,还以为死机了。后来养成习惯,上来就先设个10秒超时。
3.3 获取世界对象
客户端连上了,接下来要获取“世界”。在Carla里,“世界”就是整个仿真环境的根对象。地图、天气、车辆、行人,全都挂在它下面。
world = client.get_world()
就这么一行。拿到 world 对象之后,你就可以为所欲为了。比如获取当前地图的名字:
print(world.get_map().name)
我一般会先打印一下地图名,确认自己连对了。毕竟有时候开了多个仿真器,容易搞混。
3.4 获取蓝图库
蓝图(Blueprint)是什么?你可以把它理解成“车型模板”。Carla内置了上百种车辆、行人、传感器的模板。每个模板都定义了模型、颜色、物理属性等。
获取蓝图库很简单:
blueprint_library = world.get_blueprint_library()
然后你可以看看里面都有什么车:
for bp in blueprint_library.filter('vehicle.*'):
print(bp.id)
这里 filter('vehicle.*') 是过滤出所有以 vehicle. 开头的蓝图。Carla的蓝图命名很规范,比如 vehicle.audi.a2、vehicle.bmw.grandtourer 等等。
blueprint_library.find('vehicle.audi.a2')。我写测试脚本时,经常固定用几款车,这样每次生成的场景都一样,方便对比。
3.5 生成车辆与行人
好,重头戏来了。生成一辆车,需要三个要素:蓝图、位置、旋转角度。
我们先随机选一辆车:
vehicle_bp = random.choice(blueprint_library.filter('vehicle.*'))
然后找一个生成点。Carla地图里预置了很多 spawn_point,我们可以随机选一个:
spawn_points = world.get_map().get_spawn_points()
spawn_point = random.choice(spawn_points)
最后,生成车辆:
vehicle = world.spawn_actor(vehicle_bp, spawn_point)
就这么简单。车就出现在路上了。
如果你想生成行人,流程类似,只是蓝图要换成 walker.pedestrian.*:
walker_bp = random.choice(blueprint_library.filter('walker.pedestrian.*'))
walker_spawn_point = carla.Transform()
walker_spawn_point.location = spawn_point.location + carla.Location(x=5, y=0, z=0)
walker = world.spawn_actor(walker_bp, walker_spawn_point)
注意,行人没有预置的 spawn_point,所以我们需要自己构造一个 Transform。我一般会在车辆旁边偏移几米生成行人,这样看起来更自然。
import carla
import random
import time
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)
world = client.get_world()
blueprint_library = world.get_blueprint_library()
# 生成车辆
vehicle_bp = random.choice(blueprint_library.filter('vehicle.*'))
spawn_points = world.get_map().get_spawn_points()
spawn_point = random.choice(spawn_points)
vehicle = world.spawn_actor(vehicle_bp, spawn_point)
print(f'生成车辆: {vehicle_bp.id}')
# 生成行人
walker_bp = random.choice(blueprint_library.filter('walker.pedestrian.*'))
walker_spawn_point = carla.Transform()
walker_spawn_point.location = spawn_point.location + carla.Location(x=5, y=0, z=0)
walker = world.spawn_actor(walker_bp, walker_spawn_point)
print(f'生成行人: {walker_bp.id}')
time.sleep(5) # 让场景保持5秒
# 清理
vehicle.destroy()
walker.destroy()
print('清理完成')
3.6 避坑指南
最后,分享几个我实际项目中遇到的坑:
- 生成位置冲突:如果两个车生成在同一个点,会报错。所以尽量用
random.choice从spawn_points里选,别自己硬编码坐标。 - 蓝图不存在:有时候
blueprint_library.find()会返回None,如果你没检查就直接spawn_actor,会崩溃。记得加个if bp is not None的判断。 - 忘记清理:生成的Actor如果不
destroy(),会一直留在仿真器里。我刚开始经常忘了清理,结果跑几次脚本后,仿真器里堆满了车,卡得不行。后来我习惯在脚本末尾统一清理,或者用try...finally保证清理。
嗯,这一章的内容就这些。说白了就是“连上、拿世界、拿蓝图、生成东西”。下一章我们会让这些车真正跑起来,加上传感器,开始采集数据。到时候就有意思了。