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里实现多智能体协同,我一般用两种方式:

  1. 共享感知信息:每个智能体把自己的位置、速度、意图广播出去,其他智能体接收后做决策。
  2. 集中式调度:一个中央控制器收集所有信息,然后统一分配动作。

我个人更推荐第一种,因为更接近真实世界——每个参与者都是独立决策的。

来看一个简单的协同避让示例:

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配置,它们决定了每个参与者的“个体行为”;上层是多智能体协同,解决的是“群体互动”问题。两者缺一不可。

一个小技巧:调试多智能体协同的时候,我习惯先让所有参与者“独立运行”,确认每个个体的行为没问题后,再打开协同机制。这样出了问题能快速定位是哪个环节的锅。

好了,关于行人及交通参与者管理,核心内容就这些。记住一句话:仿真不是为了完美,而是为了暴露问题。你设计的场景越接近真实,你的算法就越经得起考验。

可可精品资料库