4. 行人与交通参与者:行人蓝图与动画控制、交通管理器配置、自定义交通流生成、行人随机行走逻辑、多智能体协同仿真
好,咱们进入第四章。这一章我把它叫做「让世界活起来」。你想想看,光有车在路上跑,那叫交通仿真。有了行人、有了复杂的交通流,这才叫城市仿真。
我个人习惯,在做自动驾驶测试时,行人的行为往往比车辆更难预测。所以这一章,咱们重点啃下行人控制和交通管理器这两个硬骨头。
4.1 行人蓝图与动画控制
CARLA 里的行人,本质上是一个「会动的模型」。它由两部分组成:蓝图(Blueprint) 和 动画控制器(Animator)。
4.1.1 获取行人蓝图
行人的蓝图 ID 通常以 walker.pedestrian.* 开头。我建议你先把所有行人蓝图列出来看看:
blueprint_library = world.get_blueprint_library()
walker_bps = blueprint_library.filter('walker.pedestrian.*')
for bp in walker_bps:
print(bp.id)
你会看到类似 walker.pedestrian.0001、walker.pedestrian.0002 这样的 ID。每个蓝图对应不同的外观——有穿西装的、有背书包的、还有牵着狗的(嗯,狗也算行人)。
4.1.2 生成行人并控制动画
生成行人的代码和生成车辆类似,但有个关键区别:行人需要控制器。
# 生成行人
walker_bp = random.choice(walker_bps)
walker_transform = random.choice(spawn_points)
walker = world.spawn_actor(walker_bp, walker_transform)
# 生成控制器
walker_controller_bp = blueprint_library.find('controller.ai.walker')
walker_controller = world.spawn_actor(walker_controller_bp, carla.Transform(), attach_to=walker)
# 启动控制器
walker_controller.start()
walker_controller.go_to_location(target_location)
这里要注意:controller.ai.walker 是一个 AI 控制器,它负责让行人走路、转向、避障。没有它,行人就是个「站桩模特」。
4.1.3 动画状态控制
行人走路是有「节奏」的。你可以通过设置速度来控制动画:
# 设置行走速度(米/秒)
walker_controller.set_max_speed(1.4) # 正常步行速度
# 设置为跑步
walker_controller.set_max_speed(3.0) # 跑步状态
# 停止行走
walker_controller.stop()
为什么会这样?因为 CARLA 内部会根据速度自动切换动画混合树。速度 0 是站立,0.5-1.5 是走路,超过 2.5 就变成跑步了。
4.2 交通管理器(Traffic Manager)配置
交通管理器,简称 TM。它是 CARLA 里控制车辆行为的「大脑」。说白了,TM 决定了车辆怎么变道、怎么等红灯、怎么避让行人。
4.2.1 创建与配置 TM
# 创建交通管理器
tm = client.get_trafficmanager(port=8000)
# 设置全局参数
tm.set_global_distance_to_leading_vehicle(2.5) # 跟车距离
tm.set_synchronous_mode(True) # 同步模式
tm.set_random_left_lanechange_probability(0.1) # 左变道概率
tm.set_random_right_lanechange_probability(0.1) # 右变道概率
我个人习惯,在同步模式下使用 TM。因为这样每一帧的决策都是确定的,方便复现问题。
4.2.2 为车辆绑定 TM
# 生成车辆后,绑定 TM
vehicle = world.spawn_actor(vehicle_bp, transform)
vehicle.set_autopilot(True, tm_port=8000)
# 或者更精细的控制
tm_vehicle = tm.get_vehicle_controller(vehicle)
tm_vehicle.set_ignore_lights_percentage(0.0) # 完全遵守红绿灯
tm_vehicle.set_ignore_signs_percentage(0.0) # 完全遵守标志
tm_vehicle.set_ignore_walkers_percentage(0.0) # 完全避让行人
ignore_walkers_percentage 设为 100,车辆会直接撞向行人。这在测试碰撞检测时有用,但平时别这么干。
4.3 自定义交通流生成
光靠 TM 的随机行为不够用。很多时候我们需要自定义交通流——比如让车流在某个路口密集,或者让所有车都走同一条路线。
4.3.1 基于路线的交通流
# 定义一条路线(由一系列 waypoint 组成)
route = []
start_waypoint = world.get_map().get_waypoint(start_location)
for i in range(20):
next_waypoints = start_waypoint.next(10.0)
if next_waypoints:
start_waypoint = next_waypoints[0]
route.append(start_waypoint.transform.location)
# 让车辆沿路线行驶
vehicle.set_autopilot(True)
tm_vehicle = tm.get_vehicle_controller(vehicle)
tm_vehicle.set_path(route)
我在项目中遇到过一个问题:路线太长了,车辆走到一半就卡住。后来发现是路线点之间的间隔太大,导致车辆找不到路径。建议 相邻路线点间隔不超过 5 米。
4.3.2 密度控制
想模拟高峰期?很简单,多生成几辆车就行:
def spawn_traffic_density(density):
"""density: 0.0 ~ 1.0"""
spawn_points = world.get_map().get_spawn_points()
num_vehicles = int(len(spawn_points) * density)
for i in range(num_vehicles):
bp = random.choice(vehicle_bps)
transform = random.choice(spawn_points)
vehicle = world.try_spawn_actor(bp, transform)
if vehicle:
vehicle.set_autopilot(True)
密度 0.3 是正常车流,0.7 以上就开始堵车了。我测试时常用 0.5 作为基准。
4.4 行人随机行走逻辑
行人的随机行走,说白了就是「走到一个随机点,再走到下一个随机点」。但这里面有讲究。
4.4.1 基本随机行走
import random
import time
def random_walk(walker_controller, walker, world):
while True:
# 在行人周围 20 米范围内选一个随机点
current_loc = walker.get_location()
target_loc = carla.Location(
x=current_loc.x + random.uniform(-20, 20),
y=current_loc.y + random.uniform(-20, 20),
z=current_loc.z
)
# 让行人走过去
walker_controller.go_to_location(target_loc)
walker_controller.set_max_speed(random.uniform(0.5, 2.0))
# 等待行人到达(或超时)
time.sleep(random.uniform(5, 15))
嗯,这里要注意:不要选到马路中间的点。行人走到路中间被车撞,虽然真实,但测试场景就乱了。
4.4.2 改进版:基于人行道的行走
def safe_random_walk(walker_controller, walker, world):
map = world.get_map()
while True:
current_loc = walker.get_location()
# 获取最近的人行道 waypoint
waypoint = map.get_waypoint(current_loc, project_to_road=False, lane_type=carla.LaneType.Sidewalk)
if waypoint:
# 在人行道上随机走
for _ in range(5):
next_wp = random.choice(waypoint.next(2.0))
if next_wp:
waypoint = next_wp
target_loc = waypoint.transform.location
else:
# 不在人行道上?那就原地待着
target_loc = current_loc
walker_controller.go_to_location(target_loc)
time.sleep(random.uniform(3, 8))
project_to_road=False 可以确保 waypoint 在人行道上。这个参数我当初找了好久才找到。
4.5 多智能体协同仿真
多智能体,就是让多个行人、多辆车之间产生交互。比如:行人过马路,车辆停下来让行。
4.5.1 行人-车辆交互
def pedestrian_crossing_scenario(world, tm):
# 生成一个行人,准备过马路
walker = spawn_pedestrian_at_sidewalk(world)
walker_controller = spawn_walker_controller(world, walker)
# 生成一辆车,从远处驶来
vehicle = spawn_vehicle_on_road(world)
vehicle.set_autopilot(True)
# 让行人走到马路对面
cross_point = carla.Location(x=walker.get_location().x + 30, y=walker.get_location().y, z=0.5)
walker_controller.go_to_location(cross_point)
# TM 会自动处理车辆避让行人
# 但我们可以手动调整参数
tm_vehicle = tm.get_vehicle_controller(vehicle)
tm_vehicle.set_distance_to_leading_vehicle(5.0) # 增大跟车距离,给行人更多空间
为什么会自动避让?因为 TM 默认开启了 ignore_walkers_percentage=0,车辆会检测前方行人并减速。
4.5.2 多行人协同
有时候需要模拟一群人同时过马路:
def group_crossing(world, num_pedestrians=5):
pedestrians = []
controllers = []
# 生成一群行人
for i in range(num_pedestrians):
walker, controller = spawn_pedestrian_with_controller(world)
pedestrians.append(walker)
controllers.append(controller)
# 让他们同时走向同一个目标
target = carla.Location(x=50, y=30, z=0.5)
for controller in controllers:
controller.go_to_location(target)
controller.set_max_speed(1.2) # 统一速度,保持队形
return pedestrians, controllers
4.6 本章知识体系
下面这张图总结了本章的核心逻辑:
这张图把本章的五个核心模块串起来了。你从中间开始看——交通参与者仿真,然后向四周发散。每个模块都有对应的代码实现和参数调优技巧。
好了,这一章的内容就到这里。记住:行人控制的关键在控制器,交通流的关键在 TM 参数,多智能体的关键在交互逻辑。把这些吃透了,你的仿真场景就能以假乱真。
可可精品资料库