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这个参数,结果控制器生成了,但行人纹丝不动。调试了半天才发现是绑定关系没建立。

控制行人行走的核心逻辑其实就三步:

  1. 生成行人
  2. 生成AI控制器并绑定
  3. 设置速度并启动

说白了,控制器就是行人的「大脑」,它负责把高级指令(比如「往前走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 本章知识体系

为了让你更直观地理解行人生成和控制的整体流程,我画了一张图:

行人生成与控制流程 1. 获取行人蓝图 walker.pedestrian.* 2. 设置生成位置 SpawnPoint / 手动坐标 3. 生成行人 spawn_actor() 4. 生成AI控制器 controller.ai.walker 5. 设置行走路径 go_to_location() 6. 启动行走 start() + set_max_speed() 随机漫游模式 go_to_location(当前位置) 自动随机转向 指定路径模式 go_to_location(路径点列表) 按顺序依次到达 两种路径模式:随机漫游(背景行人) vs 指定路径(关键行为测试)

这张图把整个流程拆成了六个步骤。你从左边看,有两种路径模式可选。我个人建议:背景行人用随机漫游,关键测试场景用指定路径。这样既保证了场景的丰富性,又能精确控制测试条件。

好了,关于行人生成和控制的内容就讲到这里。记住,行人模拟的精髓在于「可控的随机性」——既要让行人看起来自然,又要能复现特定的测试场景。多练几次,你就能找到感觉了。