交通管理器(Traffic Manager)
交通管理器(Traffic Manager)是CARLA中一个客户端模块,用于控制仿真中的特定车辆。车辆通过 carla.Vehicle.set_autopilot 方法或 command.SetAutopilot 命令注册到交通管理器。每辆车的控制通过一系列不同阶段的循环实现,每个阶段运行在独立的线程上。
适用场景:
- 为仿真填充逼真的城市交通环境。
- 自定义交通行为,以构建特定的学习或测试条件。
- 在提升计算效率的同时,开发与阶段相关的功能和数据结构。
什么是交通管理器?
交通管理器(Traffic Manager,简称 TM)是 CARLA 中用于控制仿真中处于自动驾驶(autopilot)模式车辆的模块。其目标是在仿真中生成逼真的城市交通环境。用户可通过自定义部分行为(例如设置特定的学习场景)来调整交通流。
结构化设计
TM 构建于 CARLA 客户端侧。其执行流程被划分为多个阶段,每个阶段具有独立的操作和目标。这种设计便于开发与阶段相关的功能和数据结构,同时提升计算效率。每个阶段运行在独立线程上,阶段间通过同步消息通信,信息单向流动。
用户自定义
用户可通过设置参数来控制交通流,这些参数可允许、强制或鼓励特定行为。用户可在线(online)或离线(offline)自由修改交通行为。例如,可让车辆忽略限速,或强制变道。在模拟现实场景时,灵活调整行为至关重要------自动驾驶系统必须在特定甚至非典型条件下接受训练。
架构概览

上述图表展示了 TM 的内部架构。各组件的 C++ 源码位于 LibCarla/source/carla/trafficmanager 目录下。以下是对各组件的详细说明。整体逻辑可简化为以下三步:
-
存储并更新仿真的当前状态
- Agent 生命周期与状态管理(ALSM):扫描世界,追踪所有车辆和行人,并清理已不存在的对象条目。所有数据从服务器获取,并经由多个阶段传递。ALSM 是唯一与服务器通信的组件。
- 车辆注册表(Vehicle Registry):包含一个由 TM 控制的自动驾驶车辆数组,以及一个未启用自动驾驶的行人和车辆列表。
- 仿真状态(Simulation State):缓存仿真中所有车辆和行人的位置、速度及其他附加信息。
-
计算每辆自动驾驶车辆的运动
TM 根据仿真状态,为注册表中的所有车辆生成可行的控制指令。每辆车的计算独立进行,并分为多个阶段。控制循环(Control Loop) 通过在各阶段间设置同步屏障,确保计算一致性------所有车辆必须完成当前阶段的计算后,才能进入下一阶段。每辆车依次经过以下五个阶段:
2.1 定位阶段(Localization Stage)
利用内存地图(In-Memory Map) (将仿真地图简化为路点网格)动态生成路径。在交叉口处随机选择方向。每辆车的路径由路径缓冲与车辆追踪(PBVT) 组件存储和维护,供后续阶段快速访问和修改。
2.2 碰撞阶段(Collision Stage)
沿车辆路径延伸包围盒,识别并规避潜在碰撞风险。
2.3 交通灯阶段(Traffic Light Stage)
类似碰撞阶段,识别因交通灯、停车标志和交叉口优先级对路径造成的潜在危险。
2.4 运动规划阶段(Motion Planner Stage)
基于规划路径计算车辆运动。PID 控制器确定如何到达目标路点,并将结果转换为 CARLA 控制指令,用于下一步应用。
2.5 车灯阶段(Vehicle Lights Stage)
根据环境因素(如阳光、雾、雨)和车辆行为(如下一交叉口左/右转时开启转向灯,刹车时开启制动灯),动态开关车灯。
-
在仿真中应用控制指令
将上一步生成的所有指令收集到指令数组(Command Array) 中,以批处理方式发送至 CARLA 服务器,在同一帧内统一应用。
以下章节将详细解释上述 TM 逻辑中的各个组件和阶段。
ALSM(Agent Lifecycle & State Management)
ALSM 是 TM 逻辑循环的第一步,提供仿真当前状态的上下文。
- 扫描世界,追踪所有车辆和行人的位置与速度。若启用了物理引擎,速度通过
Vehicle.get_velocity()获取;否则通过历史位置更新计算得出。 - 将所有车辆和行人的位置、速度及附加信息(如交通灯影响、包围盒等)存储在仿真状态组件中。
- 更新车辆注册表中由 TM 控制的车辆列表。
- 同步更新控制循环 和 PBVT 组件中的条目,使其与车辆注册表一致。
相关源文件:ALSM.h, ALSM.cpp
车辆注册表(Vehicle Registry)
追踪仿真中所有车辆和行人。
- 从 ALSM 接收更新后的车辆和行人列表。
- 将注册到 TM 的车辆单独存储在一个数组中,供控制循环迭代使用。
相关源文件:MotionPlannerStage.cpp
仿真状态(Simulation State)
为后续阶段提供便捷访问和修改的仿真车辆信息缓存。
- 从 ALSM 接收当前参与者的位置、速度、交通灯影响、交通灯状态等数据。
- 将所有信息缓存,避免在控制循环中重复调用服务器。
相关源文件:SimulationState.cpp, SimulationState.h
控制循环(Control Loop)
同步管理所有自动驾驶车辆的下一指令计算。包含五个阶段:定位、碰撞、交通灯、运动规划和车灯。
- 从车辆注册表接收 TM 控制的车辆数组。
- 对数组中每辆车分别进行计算。
- 将计算划分为一系列阶段。
- 在阶段间设置同步屏障,确保所有车辆完成当前阶段后才进入下一阶段,保证帧内一致性。
- 协调阶段过渡,使所有计算同步进行。
- 在最后阶段(运动规划和车灯阶段)完成后,立即将指令数组发送至服务器,避免指令计算与应用之间的帧延迟。
相关源文件:TrafficManagerLocal.cpp
内存地图(In-Memory Map)
PBVT 内部的辅助模块,用于定位阶段。
- 将地图转换为离散路点网格。
- 使用特定数据结构存储路点,包含连接关系及道路、交叉口等标识信息。
- 为这些结构分配 ID,便于快速定位附近区域的车辆。
相关源文件:InMemoryMap.cpp, SimpleWaypoint.cpp
PBVT(Path Buffer and Vehicle Tracking)
存储每辆车的预期路径,便于控制循环中快速访问数据。
- 包含一个以车辆为键的双端队列(deque)映射。
- 为每辆车存储描述当前位置和近期路径的一系列路点。
- 包含定位阶段使用的内存地图,用于将车辆关联到最近路点及可能重叠的路径。
PID 控制器(PID Controller)
运动规划阶段的辅助模块。
- 利用运动规划阶段收集的信息,估算达到目标值所需的油门、刹车和转向输入。
- 可根据控制器的具体参数化进行调整。用户可修改参数以优化行为(详见 PID 控制器相关文档)。
相关源文件:PIDController.cpp
指令数组(Command Array)
TM 逻辑循环的最后一步,接收并应用所有注册车辆的指令。
- 从运动规划阶段接收一系列
carla.VehicleControl指令。 - 将所有指令批处理,以便在同一帧内应用。
- 根据仿真是否为异步或同步模式,调用
carla.Client的apply_batch()或apply_batch_synch()将批处理指令发送至 CARLA 服务器。
相关源文件:TrafficManagerLocal.cpp
控制循环各阶段详解
阶段 1:定位阶段(Localization Stage)
为 TM 控制的车辆定义近期路径。
- 从仿真状态获取所有车辆的位置和速度。
- 利用内存地图将每辆车关联到描述其当前位置和近期路径的路点列表(车速越快,列表越长)。
- 根据变道、限速、与前车距离等规划决策更新路径。
- 将所有车辆路径存储在 PBVT 模块中。
- 比较路径以预估可能的碰撞情况,并将结果传递给碰撞阶段。
相关源文件:LocalizationStage.cpp, LocalizationUtils.cpp
阶段 2:碰撞阶段(Collision Stage)
触发碰撞危险。
- 从定位阶段接收可能路径重叠的车辆对列表。
- 沿每对车辆的路径前方延伸包围盒(测地边界),检查是否实际重叠,判断碰撞风险是否真实存在。
- 将所有可能碰撞的危险信息发送至运动规划阶段,以相应调整路径。
相关源文件:CollisionStage.cpp
阶段 3:交通灯阶段(Traffic Light Stage)
因交通信号(红绿灯、停车标志、交叉口优先级)触发危险。
- 若车辆受黄灯、红灯或停车标志影响,则设置交通危险。
- 若车辆处于无信号交叉口,则沿其路径延伸包围盒。路径重叠的车辆按"先到先出"(FIFO)顺序通行,并设置固定等待时间。
相关源文件:TrafficLightStage.cpp
阶段 4:运动规划阶段(Motion Planner Stage)
生成待应用于车辆的 CARLA 指令。
- 汇总车辆的位置与速度(仿真状态)、路径(PBVT)及危险信息(碰撞阶段和交通灯阶段)。
- 做出高层决策(如计算避免碰撞所需的刹车力度)。使用 PID 控制器根据目标值估算行为。
- 将期望运动转换为
carla.VehicleControl指令。 - 将生成的 CARLA 指令发送至指令数组。
相关源文件:MotionPlannerStage.cpp
阶段 5:车灯阶段(Vehicle Lights Stage)
根据车辆状态和环境条件激活车灯。
- 获取车辆的规划路点、车灯信息(当前状态及计划指令)和天气条件。
- 确定新车灯状态:
- 若车辆计划在下一交叉口左/右转,则开启转向灯。
- 若指令要求刹车,则开启制动灯。
- 日落到日出期间,或大雨时,开启近光灯和示宽灯。
- 大雾条件下开启雾灯。
- 若车灯状态发生变化,则更新之。
相关源文件:VehicleLightStage.cpp
使用交通管理器
车辆行为注意事项
TM 实现了通用行为模式,启用自动驾驶时需注意:
- 车辆无目标导向,仅遵循动态生成的轨迹,在接近交叉口时随机选择路径,路径无限延续。
- 车辆目标速度默认为当前限速的 70%(除非另行设置)。
- 交叉口优先级不遵循交通法规,TM 使用自有优先级系统(此限制正在改进中)。例如,环岛内车辆可能错误地让行试图驶入的车辆。
可通过 Python API 调整 TM 行为。具体方法参见 Python API 文档的 TM 章节。以下为 API 功能概要:
| 主题 | 描述 |
|---|---|
| 通用操作 | - 创建连接到指定端口的 TM 实例 - 获取 TM 连接的端口号 |
| 安全条件 | - 设置停车车辆间的最小距离(单辆车或全部) - 设置期望速度为当前限速的百分比(单辆车或全部) - 重置交通灯 |
| 碰撞管理 | - 启用/禁用某车辆与特定参与者的碰撞 - 使车辆忽略所有其他车辆 - 使车辆忽略所有行人 - 使车辆忽略所有交通灯 |
| 变道控制 | - 强制变道(忽略可能碰撞) - 启用/禁用某车辆的变道功能 |
| 混合物理模式 | - 启用/禁用混合物理模式 - 修改启用物理计算的半径 |
创建交通管理器
注意
TM 设计用于同步模式。在异步模式下使用可能导致意外或不良结果。详见"同步模式"章节。
TM 实例由 carla.Client 创建,需指定端口(默认为 8000):
python
tm = client.get_trafficmanager(port)
为一组车辆启用自动驾驶,需获取 TM 端口并设置 set_autopilot=True,同时传入 TM 端口。若未提供端口,则尝试连接默认端口(8000);若 TM 不存在,则自动创建:
python
tm_port = tm.get_port()
for v in vehicles_list:
v.set_autopilot(True, tm_port)
注意
多客户端场景下的 TM 创建/连接方式与上述示例不同。详见"运行多个交通管理器"章节。
/PythonAPI/examples/generate_traffic.py 脚本展示了如何通过脚本参数传入端口创建 TM 实例,并批量将生成的车辆注册到 TM:
python
traffic_manager = client.get_trafficmanager(args.tm_port)
tm_port = traffic_manager.get_port()
...
batch.append(SpawnActor(blueprint, transform).then(SetAutopilot(FutureActor, True, tm_port)))
...
traffic_manager.global_percentage_speed_difference(30.0)
配置自动驾驶行为
以下示例创建 TM 实例,并为特定车辆配置危险行为:忽略所有交通灯、不保持安全车距、以超过限速 20% 的速度行驶:
python
tm = client.get_trafficmanager(port)
tm_port = tm.get_port()
for v in my_vehicles:
v.set_autopilot(True, tm_port)
danger_car = my_vehicles[0]
tm.ignore_lights_percentage(danger_car, 100) # 100% 忽略红绿灯
tm.distance_to_leading_vehicle(danger_car, 0) # 与前车距离为 0
tm.vehicle_percentage_speed_difference(danger_car, -20) # 速度比限速快 20%
以下示例为同一组车辆配置温和驾驶行为:以低于限速 80% 的速度行驶、与前车保持至少 5 米距离、禁止变道:
python
tm = client.get_trafficmanager(port)
tm_port = tm.get_port()
for v in my_vehicles:
v.set_autopilot(True, tm_port)
tm.global_distance_to_leading_vehicle(5) # 全局前车距离 5 米
tm.global_percentage_speed_difference(80) # 全局速度为限速的 20%(即慢 80%)
for v in my_vehicles:
tm.auto_lane_change(v, False) # 禁止所有车辆自动变道
委托 TM 自动更新车灯
默认情况下,TM 管理的车辆不会自动更新车灯(刹车灯、转向灯等)。可通过以下方式委托 TM 为指定车辆自动管理车灯:
python
tm = client.get_trafficmanager(port)
for actor in my_vehicles:
tm.update_vehicle_lights(actor, True)
车灯管理需逐车设置,因此可同时存在启用和未启用自动车灯管理的车辆。
停止交通管理器
TM 并非需要显式销毁的参与者;当创建它的客户端停止时,TM 会自动停止(由 API 自动管理,用户无需操作)。但关闭 TM 时,必须销毁其控制的车辆 ,否则它们将静止在地图上。generate_traffic.py 脚本会自动处理:
python
client.apply_batch([carla.command.DestroyActor(x) for x in vehicles_list])
警告
关闭 TM-Server 会导致所有连接到它的 TM-Clients 一同关闭。关于 TM-Server 与 TM-Client 的区别,详见"运行多个交通管理器"章节。
确定性模式(Deterministic Mode)
在确定性模式下,TM 在相同条件下将产生完全相同的结果和行为。注意:确定性不同于录制回放功能。录制用于保存仿真日志以供回放,而确定性确保在相同条件下多次运行脚本时 TM 输出一致。
确定性模式仅在同步模式下可用。异步模式下无法实现确定性。启用前请阅读"同步模式"章节。
启用确定性模式:
python
my_tm.set_random_device_seed(seed_value)
seed_value 为整数,用于生成随机数。该值本身无关紧要,但相同种子值始终产生相同输出。两个条件相同的仿真若使用相同种子值,则具有确定性。
为在多次仿真运行中保持确定性,每次仿真都必须重新设置种子。例如,每次重载世界后需重新设置:
python
client.reload_world()
my_tm.set_random_device_seed(seed_value)
可在 generate_traffic.py 示例脚本中通过传入种子值测试确定性模式。以下示例在同步模式下生成 50 个自动驾驶参与者,并设置种子值为 9:
bash
cd PythonAPI/examples
python3 generate_traffic.py -n 50 --seed 9
警告
启用确定性模式前,CARLA 服务器和 TM 必须处于同步模式。详见 TM 同步模式文档。
混合物理模式(Hybrid Physics Mode)
混合模式允许用户为所有自动驾驶车辆(或标记为 hero 的车辆半径外的自动驾驶车辆)禁用大部分物理计算 ,从而消除车辆物理计算的性能瓶颈。禁用物理的车辆将通过瞬移移动。为保持位置更新和车速的真实性,并确保物理切换流畅,仍保留基本的线性加速度计算。
混合模式通过 Actor.set_simulate_physics() 方法切换物理计算,默认禁用。启用方式有两种:
TrafficManager.set_hybrid_physics_mode(True):为调用该方法的 TM 对象启用混合模式。- 运行
generate_traffic.py时添加--hybrid标志:该脚本会创建 TM 并生成自动驾驶车辆,传入--hybrid参数时自动启用混合模式。
可通过以下两个参数调整混合模式行为:
- 半径(默认 50 米) :相对于标记为
hero的车辆。半径内车辆启用物理,半径外禁用。通过traffic_manager.set_hybrid_physics_radius(r)修改半径大小。 - Hero 车辆 :标记为
role_name='hero'的车辆,作为半径中心。- 若无 Hero 车辆,则所有车辆物理均被禁用。
- 若有多个 Hero 车辆,则为每个 Hero 车辆创建独立的物理启用区域。
下图展示了混合模式激活时物理的启用/禁用状态:Hero 车辆标记为红色方框;物理禁用车辆标记为蓝色方框;进入 Hero 车辆影响半径后,物理启用,标记变为绿色。

运行多个交通管理器
TM 服务器与客户端
CARLA 客户端通过指定端口向服务器创建 TM。若未指定端口,则使用默认端口 8000。若在同一端口创建更多 TM,则首个 TM 成为 TM-Server ,后续 TM 成为 TM-Clients。这些角色定义了 TM 在仿真中的行为。
-
TM-Server:首个连接到空闲端口的 TM。若其他 TM(Clients)连接到同一端口,则 Server 将控制所有 Clients 的行为(如 Server 停止,则所有 Clients 停止)。
pythontm01 = client01.get_trafficmanager() # tm01 --> TM-Server (端口 8000) tm02 = client02.get_trafficmanager(5000) # tm02 --> TM-Server (端口 5000) -
TM-Client:连接到已被占用端口(即 TM-Server 端口)的 TM,其行为由 TM-Server 控制。
pythontm03 = client03.get_trafficmanager() # tm03 --> 连接到 tm01 (端口 8000) tm04 = client04.get_trafficmanager(5000) # tm04 --> 连接到 tm02 (端口 5000)
CARLA 服务器通过端口和客户端 IP(对用户隐藏)维护 TM 实例注册表。目前无法查询已创建的 TM 实例。每次尝试创建实例时,系统将自动尝试连接,并创建 TM-Server 或 TM-Client。
多客户端仿真(Multi-client Simulation)
多个 TM 连接到同一端口。首个 TM 为 Server,其余为 Clients,Server 控制所有 TM 实例的行为:
bash
# 终端 1:启动 CARLA 服务器
./CarlaUE4.sh -carla-rpc-port=4000
# 终端 2:创建 TM-Server
python3 generate_traffic.py --port 4000 --tm-port 4050
# 终端 3:创建 TM-Client(连接到同一 tm-port)
python3 generate_traffic.py --port 4000 --tm-port 4050
多 TM 仿真(Multi-TM Simulation)
多个 TM 实例连接到不同端口,各自独立控制行为:
bash
# 终端 1:启动 CARLA 服务器
./CarlaUE4.sh -carla-rpc-port=4000
# 终端 2:创建 TM-Server A
python3 generate_traffic.py --port 4000 --tm-port 4050
# 终端 3:创建 TM-Server B
python3 generate_traffic.py --port 4000 --tm-port 4550
多仿真(Multi-simulation)
同时运行多个 CARLA 服务器。TM 需连接到对应服务器端口。只要计算资源允许,TM 可同时运行多个仿真:
bash
# 终端 1:仿真 A
./CarlaUE4.sh -carla-rpc-port=4000
# 终端 2:仿真 B
./CarlaUE4.sh -carla-rpc-port=5000
# 终端 3:TM-Server A 连接到仿真 A
python3 generate_traffic.py --port 4000 --tm-port 4050
# 终端 4:TM-Server B 连接到仿真 B
python3 generate_traffic.py --port 5000 --tm-port 5050
多仿真概念独立于 TM。上述示例并行运行两个 CARLA 仿真(A 和 B),每个仿真独立创建 TM-Server。仿真 A 可运行多客户端 TM,而仿真 B 可运行多 TM 或无 TM。
常见问题 :客户端尝试连接到非当前仿真的已有 TM 时,将报错并中止连接,以防仿真间干扰。
同步模式(Synchronous Mode)
TM 专为同步模式设计 。CARLA 服务器和 TM 均需设为同步模式才能正常工作。异步模式下使用 TM 可能导致意外结果;若必须使用异步模式,仿真帧率应至少达到 20--30 FPS。
以下脚本演示如何将服务器和 TM 设为同步模式:
python
# 设置仿真为同步模式
init_settings = world.get_settings()
settings = world.get_settings()
settings.synchronous_mode = True
world.apply_settings(settings)
# 设置 TM 为同步模式
my_tm.set_synchronous_mode(True)
# 在同一客户端 tick 世界
world.tick()
# 脚本结束前务必禁用同步模式,防止服务器阻塞
settings.synchronous_mode = False
my_tm.set_synchronous_mode(False)
world.apply_settings(settings)
generate_traffic.py 示例脚本会自动将 TM 和 CARLA 服务器设为同步模式:
bash
cd PythonAPI/examples
python3 generate_traffic.py -n 50
若需异步模式,运行时添加 --async 标志。
重要准则:
- 多客户端场景中,仅 TM-Server 应设为同步模式。
- 多 TM 场景中,仅一个 TM-Server 应设为同步模式。
- ScenarioRunner 模块会自动运行 TM,并自动将其设为同步模式。
警告脚本结束前,务必禁用世界和 TM 的同步模式,否则服务器将无限等待 tick 而阻塞。
大型地图中的交通管理器
使用大型地图前,请先阅读大型地图文档。
自动驾驶车辆在大型地图中的行为取决于是否存在 Hero 车辆:
无 Hero 车辆
所有自动驾驶车辆被视为休眠参与者(dormant actors) ,行为类似混合模式:通过瞬移在地图上移动,且不会被渲染(因无 Hero 车辆触发地图瓦片流式加载)。
有 Hero 车辆
当自动驾驶车辆与 Hero 车辆距离超过 actor_active_distance 时,将变为休眠状态。通过 Python API 设置该值:
python
settings = world.get_settings()
settings.actor_active_distance = 2000 # 2km 外休眠
world.apply_settings(settings)
在 TM 中,可配置休眠车辆持续在 Hero 车辆周围重生,而非停留在地图其他区域。通过以下方法配置:
set_respawn_dormant_vehicles(True):启用休眠车辆重生。set_boundaries_respawn_dormant_vehicles(lower, upper):设置重生距离范围(单位:米)。
注意:
- 上限距离不超过大型地图的tile流式加载距离。
- 下限距离最小为 20 米。
示例:在 Hero 车辆 25--700 米范围内重生休眠车辆:
python
my_tm.set_respawn_dormant_vehicles(True)
my_tm.set_boundaries_respawn_dormant_vehicles(25, 700)
若碰撞阻止休眠车辆重生,TM 将在下一仿真步重试。
若未启用重生,休眠车辆行为取决于混合模式:
- 启用混合模式:休眠车辆通过瞬移在地图上移动。
- 未启用混合模式 :休眠车辆物理计算被禁用,将原地静止,直至不再休眠。