信号灯

Traffic Signal Lights(信号灯)可以用于在 SUMO 中仿真交通路口的信号灯,用于交通控制。 关于「信号灯」的代码例子 TransSimHub Traffic Light Example。 下面介绍 Traffic Light 的状态( state), 动作类型( action type)和使用例子:

信号灯状态定义

  • 信号灯 ID 列表 tls_ids (List[str]):场景中信号灯 ID 列表,每个信号灯拥有唯一 ID,用于区分不同的信号灯

  • 动作类型 action_type (str):信号灯支持的动作类型,目前支持 choose_next_phasenext_or_not

  • 动作间隔 delta_time (int):信号灯执行相邻动作的时间间隔,即每 delta_time 信号灯做一次动作

  • 所有信号灯 traffic_lights (dict()):用于存储场景中的所有交通信号灯

  • 当前相位 ID this_phase_index (int): 观测时信号灯的相位 ID

  • 当前相位 this_phase (List[bool]): 观测时信号灯的相位,转换为对应控制的 movement

  • 上一次相位 last_phase (List[bool]): 信号灯在上一次观测时的相位

  • 下一次相位 next_phase (List[bool]): 信号灯的相位列表中,下一次切换需要执行的相位( next_or_not 动作中需要预定义相位顺序)

  • 进口和出口对应关系 fromEdge_toEdge Dict[str, List[str]]: 信号灯控制的路口处,入口 Edge 和出口 Edge 之间的对应关系

  • 通行方向 movement_directions (Dict[str, str]):交通路口中每一个 movement 的方向

  • 车道数 movement_lane_numbers (List[int]):交通路口中每个通行方向包含的车道数

  • 运动方向ID movement_ids (List[str]):存储每个 movement ID,格式是来自那条路去那条路 (fromEdge, toEdge)

  • 相位 phase2movements (Dict[int, List[str]]):记录每个相位控制的通行方向组合

  • 可否执行动作 can_perform_action (bool):当前是否可以执行信号灯相位的切换,相位在切换时需要满足最短执行时间

对于信号灯所控制路口的交通状态,我们使用探测器来获得。 探测器用于获得路口的情况,包括车流、平均占有率等。

  • 车辆的 ID 列表 last_step_vehicle_id_list List[str]:上一次观测中,在探测器上所有的车辆的 ID 列表

  • 上次观测平均速度 last_step_mean_speed (List[float]):上一次观测中,经过探测器的车的平均速度,-1 表示没有车

  • 排队车数量 jam_length_vehicle (List[float]):当前观测中,排队车的数量

  • 排队车长度 jam_length_meters (List[float]):排队车的长度

  • 平均占有率 last_step_occupancy (List[float]):车道的平均占有率

动作定义

  • 选择下一个相位 ChooseNextPhase: 从信号灯的相位列表中选择一个作为下一个相位。

    参数

    描述

    Action (int)

    相位 ID (Phase Index)

  • 执行下一个相位 NextorNot: 保持当前相位或是切换到下一个相位。 与上面的动作设计相比,这个动作设计可以保持原有信号灯相位顺序不做改变。

    参数

    描述

    Action (int)

    保持当前相位或切换到下一个相位

    0 切换到下一个相位

    1 保持当前相位

信号灯控制例子

下面具体看一个信号灯的控制的例子(完整代码见 TransSimHub Traffic Light Control)。 下面是我们要控制的信号灯,共包含 4 个绿灯相位:

traffic_light_example

接着我们在场景中初始化信号灯。 我们需要传入要控制的信号灯的 ID,控制的动作类型,和 traci 的连接:

from tshub.traffic_light.traffic_light_builder import TrafficLightBuilder

scene_traffic_lights = TrafficLightBuilder(
  sumo=conn,
  tls_ids=['htddj_gsndj'],
  action_type='choose_next_phase'
)

接着我们通过 tls_infos 来得到 traffic light 的属性:

tls_infos = scene_traffic_lights.get_objects_infos()

返回的属性如下所示,可以看到包含每一个信号灯的「静态信息」和「动态信息」。 「静态信息」包含信号灯本身的结构信息,例如 movement_directionsmovement_lane_numbersphase2movements 等。 「动态信息」包含 last_step_mean_speedjam_length_vehiclelast_step_occupancy 等。

{
  "htddj_gsndj": {
      "id": "htddj_gsndj",
      "action_type": "choose_next_phase",
      "delta_time": 5,
      "last_step_vehicle_id_list": [
        [
          "-E5__0__background.0",
          "-E3__0__ego.1"
        ],
        [],
        [],
        [],
        [],
        [],
        [],
        [],
        [],
        [
          "E0__0__background.2",
          "E0__0__ego.0"
        ],
        [],
        [],
      ]
      "last_step_mean_speed": [
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0
      ],
      "jam_length_vehicle": [
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0
      ],
      "jam_length_meters": [
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0
      ],
      "last_step_occupancy": [
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0,
          0.0
      ],
      "this_phase": [
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          true,
          true,
          false,
          true,
          true
      ],
      "last_phase": [
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          false
      ],
      "next_phase": [
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          false,
          false
      ],
      # [fromEdge, toEdge, fromLane, toLane]
      "fromEdge_toEdge": {
          "29257863#2--r": [
              "29257863#2",
              "gsndj_n6",
              "29257863#2_0",
              "gsndj_n6_0"
          ],
          "29257863#2--s": [
              "29257863#2",
              "29257863#5",
              "29257863#2_2",
              "29257863#5_2"
          ],
          "29257863#2--l": [
              "29257863#2",
              "gsndj_s5",
              "29257863#2_4",
              "gsndj_s5_2"
          ],
          "gsndj_n7--r": [
              "gsndj_n7",
              "161701303#10",
              "gsndj_n7_0",
              "161701303#10_0"
          ],
          "gsndj_n7--s": [
              "gsndj_n7",
              "gsndj_n6",
              "gsndj_n7_2",
              "gsndj_n6_2"
          ],
          "gsndj_n7--l": [
              "gsndj_n7",
              "29257863#5",
              "gsndj_n7_3",
              "29257863#5_2"
          ],
          "161701303#7.248--r": [
              "161701303#7.248",
              "gsndj_s5",
              "161701303#7.248_0",
              "gsndj_s5_0"
          ],
          "161701303#7.248--s": [
              "161701303#7.248",
              "161701303#10",
              "161701303#7.248_2",
              "161701303#10_2"
          ],
          "161701303#7.248--l": [
              "161701303#7.248",
              "gsndj_n6",
              "161701303#7.248_3",
              "gsndj_n6_2"
          ],
          "gsndj_s4--r": [
              "gsndj_s4",
              "29257863#5",
              "gsndj_s4_0",
              "29257863#5_0"
          ],
          "gsndj_s4--s": [
              "gsndj_s4",
              "gsndj_s5",
              "gsndj_s4_2",
              "gsndj_s5_1"
          ],
          "gsndj_s4--l": [
              "gsndj_s4",
              "161701303#10",
              "gsndj_s4_3",
              "161701303#10_3"
          ]
      },
      "movement_directions": {
          "29257863#2_r": "r",
          "29257863#2_s": "s",
          "29257863#2_l": "l",
          "gsndj_n7_r": "r",
          "gsndj_n7_s": "s",
          "gsndj_n7_l": "l",
          "161701303#7.248_r": "r",
          "161701303#7.248_s": "s",
          "161701303#7.248_l": "l",
          "gsndj_s4_r": "r",
          "gsndj_s4_s": "s",
          "gsndj_s4_l": "l"
      },
      "movement_lane_numbers": {
          "29257863#2_r": 1,
          "29257863#2_s": 3,
          "29257863#2_l": 2,
          "gsndj_n7_r": 1,
          "gsndj_n7_s": 2,
          "gsndj_n7_l": 1,
          "161701303#7.248_r": 1,
          "161701303#7.248_s": 2,
          "161701303#7.248_l": 1,
          "gsndj_s4_r": 1,
          "gsndj_s4_s": 2,
          "gsndj_s4_l": 1
      },
      "movement_ids": [
          "161701303#7.248_l",
          "161701303#7.248_r",
          "161701303#7.248_s",
          "29257863#2_l",
          "29257863#2_r",
          "29257863#2_s",
          "gsndj_n7_l",
          "gsndj_n7_r",
          "gsndj_n7_s",
          "gsndj_s4_l",
          "gsndj_s4_r",
          "gsndj_s4_s"
      ],
      "phase2movements": {
          "0": [
              "gsndj_n7--r",
              "gsndj_s4--r",
              "gsndj_n7--s",
              "gsndj_s4--s"
          ],
          "1": [
              "gsndj_n7--l",
              "gsndj_s4--l"
          ],
          "2": [
              "161701303#7.248--s",
              "29257863#2--r",
              "161701303#7.248--r",
              "29257863#2--s"
          ],
          "3": [
              "161701303#7.248--l",
              "29257863#2--l"
          ]
      },
      "can_perform_action": true
  }
}

这里我们设置的动作类型是 choose_next_phase,也就是选择下一个相位。 于是我们的动作就是制定下一个相位的 ID 什么。 下面是控制的例子,我们传入 ‵phase index`:

scene_traffic_lights.control_objects({'htddj_gsndj':action_index})

如果我们将 if_sumo_visualization 设置为 True,可以看到仿真画面。

traffic_light_sumo_example