4. 行人及交通参与者管理:行人行为树、交通管理器配置、多智能体协同
说实话,做自动驾驶仿真,最头疼的不是车怎么开,而是路上那些“不按套路出牌”的行人和其他交通参与者。我刚开始用CARLA那会儿,就吃过这个亏——车跑得挺好,结果一个行人突然横穿马路,整个场景直接崩了。嗯,今天咱们就来聊聊这块硬骨头。
4.1 行人行为树:让“路人”更像真人
CARLA里的行人,默认行为其实挺傻的。他们要么站着不动,要么沿着固定路线走。你想想看,真实世界哪有这样的?所以我们需要用行为树来给他们“注入灵魂”。
我个人习惯用py_trees这个库来构建行为树。说白了,行为树就是一套决策逻辑——行人看到红灯会停,看到车来了会躲,看到绿灯会加速通过。
核心思路:把行人的行为拆解成若干个节点,比如“行走”、“等待”、“避让”、“观察”。然后通过条件判断来切换这些节点。
举个例子,一个简单的行人过马路行为树:
import py_trees
# 创建根节点
root = py_trees.composites.Sequence("行人过马路")
# 子节点:观察路况
observe = py_trees.behaviours.Success("观察路况")
# 子节点:判断是否安全
safe_check = py_trees.behaviours.Success("安全检测")
# 子节点:执行过马路
cross = py_trees.behaviours.Success("过马路")
root.add_children([observe, safe_check, cross])
# 运行行为树
for i in range(100):
root.tick_once()
我在项目中遇到过一个问题:行人走到一半突然停在路中间。后来发现是行为树的“安全检测”节点太保守了,只要远处有车就判定不安全。我调整了检测距离和速度阈值,效果就好多了。
避坑指南:我曾经把行为树的更新频率设得太高(每帧都更新),结果行人像抽风一样来回切换状态。建议控制在5-10Hz,也就是每0.1-0.2秒更新一次决策。
4.2 交通管理器配置:给所有参与者“立规矩”
交通管理器(Traffic Manager,简称TM)是CARLA里控制非玩家车辆和行人的核心模块。它就像一个交通警察,给每个参与者分配“路权”。
配置TM其实不难,但有几个参数特别关键:
| 参数名 | 作用 | 我常用的值 |
|---|---|---|
| global_distance_to_leading_vehicle | 跟车距离(米) | 2.0 - 5.0 |
| vehicle_percentage_speed_difference | 速度偏差百分比 | -20 ~ +10 |
| ignore_lights_percentage | 闯红灯概率 | 0(严格)或 10(模拟不守规矩) |
| collision_detection | 碰撞检测开关 | True(必须开) |
配置代码也很直接:
import carla
# 获取世界和交通管理器
world = client.get_world()
tm = client.get_trafficmanager(8000) # 端口号
# 配置全局参数
tm.global_percentage_speed_difference(-10.0) # 所有车比限速慢10%
tm.global_distance_to_leading_vehicle(3.0) # 跟车距离3米
tm.set_global_ignore_lights_percentage(0) # 绝不闯红灯
# 为特定车辆设置参数
vehicle = world.get_actors().filter('vehicle.*')[0]
tm.ignore_lights_percentage(vehicle, 20) # 这辆车有20%概率闯红灯
你想想看,如果所有车都严格遵守交规,那仿真场景就太理想化了。我一般会给10%-20%的车辆设置一些“违规行为”,这样更接近真实路况。
注意:TM的端口号不要和服务器端口冲突。我习惯用8000-8010之间的端口,每个客户端独立一个端口。
4.3 多智能体协同:让车和行人“对话”
多智能体协同,说白了就是让车、行人、自行车这些参与者之间能互相感知、互相配合。这不是简单的“你走你的,我走我的”,而是要有信息交互。
CARLA里实现多智能体协同,我一般用两种方式:
- 共享感知信息:每个智能体把自己的位置、速度、意图广播出去,其他智能体接收后做决策。
- 集中式调度:一个中央控制器收集所有信息,然后统一分配动作。
我个人更推荐第一种,因为更接近真实世界——每个参与者都是独立决策的。
来看一个简单的协同避让示例:
class PedestrianAgent:
def __init__(self, actor):
self.actor = actor
self.position = actor.get_location()
self.velocity = actor.get_velocity()
self.intent = "crossing" # 意图:过马路
def share_info(self):
# 广播自身信息
return {
'id': self.actor.id,
'pos': self.position,
'vel': self.velocity,
'intent': self.intent
}
class VehicleAgent:
def __init__(self, actor):
self.actor = actor
self.position = actor.get_location()
self.speed = actor.get_velocity().length()
def react_to_pedestrian(self, ped_info):
# 根据行人信息做出反应
distance = self.position.distance(ped_info['pos'])
if distance < 10.0 and ped_info['intent'] == 'crossing':
# 减速让行
self.actor.apply_control(carla.VehicleControl(throttle=0.0, brake=1.0))
print(f"车辆{self.actor.id}让行行人{ped_info['id']}")
我在实际项目中遇到过一个问题:多个行人同时过马路时,车辆不知道该让谁。后来我加了一个“优先级”机制——老人、小孩、推婴儿车的行人优先级最高,普通成年人次之。这样车辆就能做出合理的避让决策了。
多智能体协同的关键:不是让所有参与者都完美配合,而是让它们能处理“意外”。比如行人突然折返、自行车突然变道——这些才是仿真中最有价值的部分。
4.4 知识体系总览
下面这张图是我自己梳理的行人与交通参与者管理框架,你可以对照着理解:
这张图把三个核心模块串起来了。你从下往上看:底层是行为树和TM配置,它们决定了每个参与者的“个体行为”;上层是多智能体协同,解决的是“群体互动”问题。两者缺一不可。
一个小技巧:调试多智能体协同的时候,我习惯先让所有参与者“独立运行”,确认每个个体的行为没问题后,再打开协同机制。这样出了问题能快速定位是哪个环节的锅。
好了,关于行人及交通参与者管理,核心内容就这些。记住一句话:仿真不是为了完美,而是为了暴露问题。你设计的场景越接近真实,你的算法就越经得起考验。
可可精品资料库