4、生成行人:行人蓝图、生成行人、控制行人行走、设置行走路径
好,咱们进入第四讲。前面几章咱们一直在跟车打交道,说实话,车在CARLA里算是「乖孩子」,行为模式相对固定。但行人不一样——行人随机性大,路径更复杂,稍不注意就给你来个「鬼探头」。我在做自动驾驶测试时,行人的模拟往往是整个场景里最头疼的部分。今天咱们就把这块啃下来。
4.1 行人蓝图:先认识一下「演员」
在CARLA里,行人也是一种蓝图(Blueprint)。跟车辆一样,我们需要先拿到蓝图库,然后筛选出行人相关的蓝图。
# 获取所有行人蓝图
walker_blueprints = world.get_blueprint_library().filter('walker.pedestrian.*')
我个人习惯先打印出来看看有哪些类型:
for bp in walker_blueprints:
print(bp.id)
你会看到类似这样的输出:
walker.pedestrian.0012
walker.pedestrian.0014
walker.pedestrian.0015
...
嗯,这里要注意:行人蓝图的数量远少于车辆蓝图。CARLA默认大概有几十种行人模型,男女老少都有。我建议你至少随机选3-5种不同的行人,这样场景看起来更真实。
bp.set_attribute('color', '255,0,0') 可以给行人穿红衣服。不过说实话,我在项目中很少改这个,默认的随机颜色已经够用了。
4.2 生成行人:别让它们「穿模」
生成行人的API跟生成车辆类似,但有个关键区别——行人需要先设置好位置和朝向。你想想看,如果行人生成时卡在墙里或者悬在半空,那画面多诡异。
# 选择一个行人蓝图
walker_bp = random.choice(walker_blueprints)
# 设置生成位置(建议用SpawnPoint)
spawn_point = random.choice(world.get_map().get_spawn_points())
# 生成行人
walker = world.spawn_actor(walker_bp, spawn_point)
我曾经在项目里遇到过一个问题:行人生成后直接掉到地面以下。排查了半天,发现是spawn_point的z坐标设成了0。CARLA的地面高度通常在0左右,但有些地图的地形有起伏。所以我的建议是:用地图自带的SpawnPoint,或者手动调整z值到合适高度。
set_autopilot(True)。行人的控制逻辑是独立的,需要专门的控制器。别搞混了。
4.3 控制行人行走:核心是「控制器」
行人的控制跟车辆完全不同。车辆有油门、刹车、方向盘,行人只有两个核心参数:速度和方向。CARLA为此提供了专门的WalkerControl类。
# 创建行人控制器
walker_controller = world.spawn_actor(
blueprint_library.find('controller.ai.walker'),
walker.get_transform(),
attach_to=walker
)
# 设置行走速度(单位:km/h)
walker_controller.set_max_speed(5.0) # 正常步行速度
# 开始行走
walker_controller.start()
这里有个容易踩的坑:控制器必须绑定到行人身上。我刚开始做的时候,忘了attach_to=walker这个参数,结果控制器生成了,但行人纹丝不动。调试了半天才发现是绑定关系没建立。
控制行人行走的核心逻辑其实就三步:
- 生成行人
- 生成AI控制器并绑定
- 设置速度并启动
说白了,控制器就是行人的「大脑」,它负责把高级指令(比如「往前走5米」)转换成具体的运动。
4.4 设置行走路径:让行人「有目的」地走
光让行人走还不够,你得告诉它往哪走。CARLA提供了两种路径设置方式:
4.4.1 随机漫游模式
最简单的方式——让行人自己瞎逛。适合测试场景中的「背景行人」。
# 设置随机漫游
walker_controller.go_to_location(walker.get_location())
walker_controller.set_max_speed(3.0)
这种方式下,行人会随机选择方向,走到地图边界或者遇到障碍物时会自动转向。嗯,说白了就是「无头苍蝇模式」。我在做城市交通流测试时,一般会用这种方式填充人行道。
4.4.2 指定路径模式
如果你想让行人走一条固定路线(比如横穿马路、走到公交站),就需要手动设置路径点。
# 定义路径点列表
path_points = [
carla.Location(x=100, y=50, z=0),
carla.Location(x=120, y=50, z=0),
carla.Location(x=140, y=60, z=0),
carla.Location(x=160, y=70, z=0)
]
# 依次让行人走向每个点
for point in path_points:
walker_controller.go_to_location(point)
time.sleep(5) # 等待行人走到目标点
这里要注意:go_to_location是异步的,它不会等行人走到才返回。所以你需要自己控制节奏。我一般会在每个路径点之间加一个time.sleep,或者用world.tick()来同步。
4.5 完整示例:生成并控制一个行人
最后,咱们把上面的知识点串起来,写一个完整的示例:
import carla
import random
import time
def spawn_and_control_walker(world):
# 1. 获取行人蓝图
walker_bp = random.choice(world.get_blueprint_library().filter('walker.pedestrian.*'))
# 2. 设置生成位置
spawn_point = random.choice(world.get_map().get_spawn_points())
# 3. 生成行人
walker = world.spawn_actor(walker_bp, spawn_point)
print(f'生成了行人: {walker_bp.id}')
# 4. 生成控制器
controller_bp = world.get_blueprint_library().find('controller.ai.walker')
walker_controller = world.spawn_actor(controller_bp, walker.get_transform(), attach_to=walker)
# 5. 设置路径(沿x轴正方向走)
start_location = walker.get_location()
target_location = carla.Location(
x=start_location.x + 20,
y=start_location.y,
z=start_location.z
)
# 6. 启动行走
walker_controller.start()
walker_controller.go_to_location(target_location)
walker_controller.set_max_speed(4.0)
# 7. 等待行人到达
while True:
current_loc = walker.get_location()
distance = current_loc.distance(target_location)
if distance < 1.0:
print('行人到达目标点')
break
world.tick()
time.sleep(0.1)
# 8. 清理
walker_controller.stop()
walker_controller.destroy()
walker.destroy()
# 主程序
client = carla.Client('localhost', 2000)
client.set_timeout(10.0)
world = client.get_world()
spawn_and_control_walker(world)
这个示例涵盖了从生成到控制再到清理的完整流程。你想想看,如果把这个逻辑封装成一个函数,再配合循环,就能生成一群行人,模拟出真实的街道场景。
4.6 本章知识体系
为了让你更直观地理解行人生成和控制的整体流程,我画了一张图:
这张图把整个流程拆成了六个步骤。你从左边看,有两种路径模式可选。我个人建议:背景行人用随机漫游,关键测试场景用指定路径。这样既保证了场景的丰富性,又能精确控制测试条件。
好了,关于行人生成和控制的内容就讲到这里。记住,行人模拟的精髓在于「可控的随机性」——既要让行人看起来自然,又要能复现特定的测试场景。多练几次,你就能找到感觉了。