CARLA Traffic Manager
一、什么是Traffic Manager
1、Traffic Manager简介
交通管理器 (TM) 是在模拟中以自动驾驶模式控制车辆的模块。其目标是使用真实的城市交通状况填充模拟,按照规则控制车辆的行为。
2、Traffic Manager框架
3、Traffic Manager模块
二、Traffic Manager控制方法
1、TM控制交通参与者的自动驾驶的规则
a)车辆遵循动态生成的轨迹,在接近路口时随机选择路径。
b)车辆的默认目标速度为当前道路速度限制的70%。
c)TM优先使用自己的控制系统而不是交通规则。
2、TM控制交通参与者行为的API摘要
2.1 混合物理模式介绍:
Hybrid physics mode使用了两种不同的物理引擎:经典物理引擎和连续物理引擎。
a)在Hybrid physics mode中,车辆被建模成经典力学中的质点,使用经典物理引擎来计算车辆的动力学行为。这种建模方法可以提高计算效率,提高运行帧率。
b)在Hybrid physics mode中,使用了连续物理引擎来模拟车辆的轮胎和悬架系统。这样做可以确保车辆在高速行驶和弯道驾驶时的物理行为和真实情况相符合。
c)Hybrid physics mode的优点是可以在保持较高物理精度的同时提高计算效率,使得用户可以更快速地迭代和测试自动驾驶算法。
2.2 混合物理模式半径触发:
红色标签的是主车,绿色标签是启动混合物理模式的车辆(主车触发范围内),蓝色标签是禁用物理模式的车辆(主车触发范围外),通过设置混合物理模式的半径可以设定主车的触发范围。
3、TM控制交通参与者行为的API
a)Carla官方Traffic Manager API链接:
https://carla.readthedocs.io/en/latest/python_api/#carlatrafficmanager
b)Carla常用的Traffic Manager API介绍:
– 常用的方法:
- distance_to_leading_vehicle(self, actor, distance)
设置车辆与其他车辆必须保持的最小距离(以米为单位)。距离以米为单位,会影响最小移动距离。它是从车辆对象的前到后计算的。
- Parameters:
- actor (carla.Actor) - 正在更改其最小距离的车辆。
- distance (float - meters) - 两车之间的最小距离。
- force_lane_change(self, actor, direction)
强制车辆改入其左侧或右侧的车道(如果存在)。无论如何,此方法都会应用变道,而不考虑可能的碰撞。
- Parameters:
- actor (carla.Actor) - 需要执行变道的车辆。
- direction (bool) - 目的地车道。True 是右边车道,False 是左边车道。
- ignore_lights_percentage(self, actor, perc)
在每帧运行一次的红绿灯阶段,此方法设置车辆忽略交通信号灯的几率。
- Parameters:
- actor (carla.Actor) - 需要忽略交通灯的对象。
- perc (float) -介于 0 和 100 之间。交通信号灯将被忽略的次数。
- ignore_vehicles_percentage(self, actor, perc)
在每帧运行一次的碰撞检测阶段,此方法设置了与车辆忽略另一辆车碰撞的百分比几率。
- Parameters:
- actor (carla.Actor) - 将忽略其他车辆的车辆。
- perc (float) -介于 0 和 100 之间。交通信号灯将被忽略的次数。
- shut_down(self)
关闭Traffic Manager
- update_vehicle_lights(self, actor, do_update)
设置交通管理器是否负责更新车辆指示灯。默认为False。交通管理器不会更改车辆的车灯状态,除非其自动更新状态为True。
- Parameters:
- actor (carla.Actor) - 灯光状态正在更改的车辆。
- perc (float) - 如果为 True,则交通管理员将管理指定车辆的车辆灯。
- vehicle_lane_offset(self, offset)
设置离中心线的车道偏移量。正值表示向右偏移,负值表示向左偏移。默认为0。
- Parameters:
- offset (float) - 车道偏移偏离中心线的位移。
- vehicle_percentage_speed_difference(self, actor, percentage)
设置车辆的预期速度与其当前道路速度限制的差值。通过将percentage设置为负值,可以超出速度限制。 默认值为 30。
- Parameters:
- offset (float) - 车道偏移偏离中心线的位移。
– 常用的查询:
- get_all_actions(self, actor)
返回Traffic Manager将在后续步骤中执行的所有已知操作(即道路选项和航点)
- Parameters:
- actor (carla.Actor) - 要查询的演员。
- Return:
- 返回每个元素的列表如下 - [道路选项(字符串,例如“左”,“右”,“直”),下一个航点(carla.Waypoint)]
- get_next_actions(self, actor)
返回Traffic Manager将在后续步骤中执行的下一个已知道路选项和航点
- Parameters:
- actor (carla.Actor) - 要查询的演员。
- Return:
- 返回两个元素的列表 - [道路选项(字符串,例如“左”,“右”,“直”),下一个航点(carla.Waypoint)]
– 常用的设置:
- set_desired_speed(self, actor, speed)
将车辆的速度设置为指定值。
- Parameters:
- actor (carla.Actor) - 需要设置速度的演员。
- speed (float) - 车辆的行驶速度。
- set_global_distance_to_leading_vehicle(self, distance)
设置车辆必须与其余车辆保持的最小距离(以米为单位)。距离以米为单位,会影响最小移动距离。它是从车辆对象的中心到中心计算的。
- Parameters:
- distance (float - meters) - 车辆最小距离。
- set_hybrid_physics_mode(self, enabled=False)
启用或禁用混合物理模式。在这种模式下,距离自我车辆超过一定半径的车辆将被禁用其物理特性。不计算车辆动力学将降低计算成本。车辆将被传送。
- Parameters:
- enabled (bool) - 如果为True则启用。
- set_hybrid_physics_radius(self, r=50.0)
启用混合物理的情况下,更改启用物理的影响区域的半径。
- Parameters:
- r (float - meters) - 半径长度。
- set_path(self, actor, path)
设置车辆在Traffic Manager控制时要遵循的位置列表。
- Parameters:
- actor (carla.Actor) - 需要设置位置的演员。
- path (list) - 演员要跟踪的位置(carla.Locations )。
- set_route(self, actor, path)
设置车辆在Traffic Manager控制时要遵循的路线指令列表。可能的路线说明是“左”,“右”,“直”。
- Parameters:
- actor (carla.Actor) - 必须遵循给定路由说明的参与者。
- path (list) - 车辆要遵循的路线指令(string)列表如,‘Left’, ‘Right’, ‘Straight’。
- set_synchronous_mode(self, mode_switch=True)
设置Traffic Manager为同步模式。
- Parameters:
- mode_switch (bool) - 如果为 True,则启用 TM 同步模式。。
三、Traffic Manager 使用方法
1、创建Traffic Manager实例
a)创建Traffic Manager实例
注意:TM 设计为在同步模式下工作。在异步模式下使用 TM 可能会导致意外和不良结果。
tm = client.get_trafficmanager(port)
b)设置一组车辆的自动驾驶
- 要启用一组车辆的自动驾驶,检索TM实例的端口并将set_autopilot设置为True,同时通过TM端口。如果没有提供端口,它将尝试连接到默认端口(8000)中的TM。如果TM不存在,它将创建一个。
tm_port = tm.get_port()
for v in vehicles_list:
v.set_autopilot(True,tm_port)
2、配置车辆的自动驾驶行为
- 下面的示例将相同的车辆列表设置为自动驾驶仪,但将它们配置为适度的驾驶行为。车辆的行驶速度比当前限速慢 80%,与其他车辆之间至少留出 5 米的距离,并且从不进行变道:
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)
tm.global_percentage_speed_difference(80)
for v in my_vehicles:
tm.auto_lane_change(v,False)
3、设置车灯自动更新
- 默认情况下,TM 管理的车辆的车辆灯(制动、转向指示灯等)永远不会更新。可以使用 TM 来更新给定车辆参与者的车灯:
tm = client.get_trafficmanager(port)
for actor in my_vehicles:
tm.update_vehicle_lights(actor, True)
4、停止运行TM
- TM不是需要销毁的演员;当创建它的客户端停止时,它将停止。这由 API 自动管理,用户无需执行任何操作。但是,当关闭TM时,用户必须摧毁由它控制的车辆,否则它们将在地图上保持不动。脚本会自动执行此操作:
client.apply_batch([carla.command.DestroyActor(x) for x in vehicles_list])
5、设置TM同步模式
- TM 设计为在同步模式下工作。CARLA 服务器和 TM 都应设置为同步才能正常运行。在异步模式下使用 TM 可能会导致意外和不希望的结果,但是,如果需要异步模式,则模拟应至少以 20-30 fps 的速度运行。
下面的脚本演示了如何将服务器和 TM 设置为同步模式:
...
# 设置仿真方式为同步模式
init_settings = world.get_settings()
settings = world.get_settings()
settings.synchronous_mode = True
# 设置Traffic Manager为同步模式
my_tm.set_synchronous_mode(True)
...
# 并在同一个客户端中模拟一帧物理时间
world.apply_settings(init_settings)
world.tick()
...
# 在脚本结束之前总是禁用同步模式,以防止服务器在等待tick时阻塞
settings.synchronous_mode = False
my_tm.set_synchronous_mode(False)
6、设置参与者睡眠与重生
- 不存在主车:
- 所有自动驾驶车辆都将被视为休眠演员,休眠的自动驾驶参与者将像在混合模式下一样在地图上移动(物理被禁用的战车将通过传送移动。保持线性加速度的基本计算,以确保位置更新和车速保持真实。)。车辆不会被渲染,因为没有英雄车辆来触发地图图块流。
- 存在主车:
- 车辆休眠:自动驾驶车辆在超过定义的值时将进入休眠状态。
settings = world.get_settings()
# 距离主车距离超过2km的车辆将睡眠。
settings.actor_active_distance = 2000
world.apply_settings(settings)
-
车辆重生:在TM中,休眠Actor可以配置为在英雄战车周围持续重生。战车将在英雄战车的用户可定义距离内重生上下限范围。注意,最小下限距离为 20m。
-
要在英雄战车 25 米和 700 米范围内重生休眠战车:
my_tm.set_respawn_dormant_vehicles(True)
my_tm.set_boundaries_respawn_dormant_vehicles(25,700)
四、TM车辆路径规划
注意:以下例程为官方内容
- 首先,我们将选择一些航点来构建我们的路径。生成点是方便的航点,与之前一样,我们可以使用 CARLA 的调试工具在地图上绘制生成点的位置。
# 在地图上用数字标出刷出点的位置
for i, spawn_point in enumerate(spawn_points):
world.debug.draw_string(spawn_point.location, str(i), life_time=10)
# 在同步模式,我们需要设置俯视图的观察者视角
while True:
world.tick()
- 我们选择生成点和航点,在城镇内创建两个汇聚的交通流,造成拥堵,这可能是一个有趣的场景,可以呈现给自动驾驶代理。
spawn_points = world.get_map().get_spawn_points()
# 路径一的起点
spawn_point_1 = spawn_points[32]
# 选择路径一的轨迹点
route_1_indices = [129, 28, 124, 33, 97, 119, 58, 154, 147]
route_1 = []
for ind in route_1_indices:
route_1.append(spawn_points[ind].location)
# 路径二的起点
spawn_point_2 = spawn_points[149]
# 选择路径二的轨迹点
route_2_indices = [21, 76, 38, 34, 90, 3]
route_2 = []
for ind in route_2_indices:
route_2.append(spawn_points[ind].location)
# 将轨迹点打印到地图上面
world.debug.draw_string(spawn_point_1.location, 'Spawn point 1', life_time=30, color=carla.Color(255,0,0))
world.debug.draw_string(spawn_point_2.location, 'Spawn point 2', life_time=30, color=carla.Color(0,0,255))
for ind in route_1_indices:
spawn_points[ind].location
world.debug.draw_string(spawn_points[ind].location, str(ind), life_time=60, color=carla.Color(255,0,0))
for ind in route_2_indices:
spawn_points[ind].location
world.debug.draw_string(spawn_points[ind].location, str(ind), life_time=60, color=carla.Color(0,0,255))
while True:
world.tick()
- 现在我们已经选择了生成点和航点,现在可以开始生成流量并将生成的载具设置为遵循我们的航点列表。
# 创建生成车辆的间隔时间
spawn_delay = 20
counter = spawn_delay
# 设置生成车辆的上限数量
max_vehicles = 200
# 路径一与路径二点交替生成标志位,alt为True生成路径一
alt = False
spawn_points = world.get_map().get_spawn_points()
while True:
world.tick()
n_vehicles = len(world.get_actors().filter('*vehicle*'))
vehicle_bp = random.choice(blueprints)
# 设置每隔20帧重新生成车辆并赋予自动驾驶行为、行驶轨迹与行为。
if counter == spawn_delay and n_vehicles < max_vehicles:
# 在轨迹1和轨迹二起点交替生成车辆
if alt:
vehicle = world.try_spawn_actor(vehicle_bp, spawn_point_1)
else:
vehicle = world.try_spawn_actor(vehicle_bp, spawn_point_2)
if vehicle: # 如果车辆成功生成
vehicle.set_autopilot(True) # TM控制车辆自动驾驶
#设置自动更新车辆车灯
traffic_manager.update_vehicle_lights(vehicle, True)
#设置随机左右变道概率为0
traffic_manager.random_left_lanechange_percentage(vehicle, 0)
traffic_manager.random_right_lanechange_percentage(vehicle, 0)
#关闭自动变道功能
traffic_manager.auto_lane_change(vehicle, False)
# 交替生成轨迹路径
if alt:
traffic_manager.set_path(vehicle, route_1)
alt = False
else:
traffic_manager.set_path(vehicle, route_2)
alt = True
vehicle = None
counter -= 1
elif counter > 0:
counter -= 1
elif counter == 0:
counter = spawn_delay
- 使用上面的代码,我们创建了两个由 TM 功能引导的来自地图两侧的汇聚流量流。这导致镇中心的一条道路拥堵。这种技术可以在更大范围内用于模拟自动驾驶汽车的多个棘手情况,例如繁忙的环形交叉路口或高速公路交叉路口。