使用Sumo以及traci实现交叉口信号灯自适应控制


使用Sumo以及traci实现交叉口信号灯自适应控制



使用Sumo以及traci实现交叉口信号灯感应控制

Sumo作为比较常用的交通仿真软件,常用于各范围的路网仿真。今天研究一下怎么通过Python和Traci结合,实现交叉口信号灯自适应控制。

一、什么是交叉口感应控制

交通信号控制方式是应用于道路交通信号控制系统,为控制和调整交通流运行状态,按照交通信号控制方案所执行的特定控制方式。国标《道路交通信号控制系统术语》(GB/T 31418-2015)、行标《《道路交通信号控制方式 第1部分:通用技术条件》(GA/T 527.1-2015)、美国《Signal Timing Mannual》对感应控制(actuated)和自适应控制(adaptive)都做了相关定义和描述。标准中对“感应控制”的描述为道路交通信号控制机根据检测器测得的交通流信息来调节信号显示时间的控制方式。

以行业标准《道路交通信号控制方式 第1部分:通用技术条件》(GA/T 527.1-2015)种描述的“单点感应控制”:根据交通流检测器测定到达交叉口进口道的交通需求,对预先设定的交通信号控制方案进行执行相位的信号配时优化调整,也可选择执行预设相位、优化相序,以减少停车延误、排队长度为目标。

根据检测器布设方式,可以将感应控制分为半感应控制和全感应控制。半感应控制只在部分进口道上设置检测器,这种情况下交叉口仅部分相位有感应请求。而全感应控制在所有进口道上都设置检测器,这种情况下交叉口所有相位均有感应请求。结合控制范围,可以将感应控制划分为单点感应控制和干线感应协调控制。自适应控制可以划分为单点自适应控制、干线自适应控制、区域自适应控制。
感应控制

二、Traci中的感应控制实现流程

1.感应控制逻辑

感应控制实现逻辑如下:

def run():
    """execute the TraCI control loop"""
    step = 0
    # we start with phase 2 where EW has green
    traci.trafficlight.setPhase("0", 2)
    while traci.simulation.getMinExpectedNumber() > 0:
        traci.simulationStep()
        if traci.trafficlight.getPhase("0") == 2:
            # we are not already switching
            if traci.inductionloop.getLastStepVehicleNumber("0") > 0:
                # there is a vehicle from the north, switch
                traci.trafficlight.setPhase("0", 3)
            else:
                # otherwise try to keep green for EW
                traci.trafficlight.setPhase("0", 2)
        step += 1
    traci.close()
    sys.stdout.flush()

当有车辆进入布设的线圈内部时,检测器检测到车辆存在,切换相位。这里对Traci中的这部分代码进行详细讲解:

traci.trafficlight.setPhase("0", 2)

这里是设置信号灯初始相位为2相位,对应的相位信息,我们可以在xml文件中进行设置,对应的trafficlight的文档中,可以看到setPhase的相关内容:
traci.trafficlight.setPhase方法
可以看到,setPhase的作用是切换相位,在相位列表中,按照每一个相位对应的索引,比如[‘南北直行放行’,‘南北左转放行’,’东西直行放行‘,‘东西左转放行’],setPhase(‘0’,2)表示对id为0的信号灯,切换到第索引为2的相位,即东西直行放行。
那么是怎么对是否有车进入线圈进行判断的,这里用的是

traci.inductionloop.getLastStepVehicleNumber()

traci.inductionloop.getLastStepVehicleNumber()方法的介绍如下:
traci.inductionloop.getLastStepVehicleNumber()方法
即参数输入为线圈id,返回为上一仿真step中在线圈内的车辆数量,这里用了一个判断,traci.inductionloop.getLastStepVehicleNumber(’0‘)>0,即还有车在上一仿真步长中在线圈内。

2.仿真过程

代码如下(示例):

#!/usr/bin/env python
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
# Copyright (C) 2009-2022 German Aerospace Center (DLR) and others.
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0/
# This Source Code may also be made available under the following Secondary
# Licenses when the conditions for such availability set forth in the Eclipse
# Public License 2.0 are satisfied: GNU General Public License, version 2
# or later which is available at
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later

# @file    runner.py
# @author  Lena Kalleske
# @author  Daniel Krajzewicz
# @author  Michael Behrisch
# @author  Jakob Erdmann
# @date    2009-03-26

from __future__ import absolute_import
from __future__ import print_function

import os
import sys
import optparse
import random

# we need to import python modules from the $SUMO_HOME/tools directory
if 'SUMO_HOME' in os.environ:
    tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
    sys.path.append(tools)
else:
    sys.exit("please declare environment variable 'SUMO_HOME'")

from sumolib import checkBinary  # noqa
import traci  # noqa


def generate_routefile():
    random.seed(42)  # make tests reproducible
    N = 3600  # number of time steps
    # demand per second from different directions
    pWE = 1. / 10
    pEW = 1. / 11
    pNS = 1. / 30
    with open("data/cross.rou.xml", "w") as routes:
        print("""<routes>
        <vType id="typeWE" accel="0.8" decel="4.5" sigma="0.5" length="5" minGap="2.5" maxSpeed="16.67" \
guiShape="passenger"/>
        <vType id="typeNS" accel="0.8" decel="4.5" sigma="0.5" length="7" minGap="3" maxSpeed="25" guiShape="bus"/>

        <route id="right" edges="51o 1i 2o 52i" />
        <route id="left" edges="52o 2i 1o 51i" />
        <route id="down" edges="54o 4i 3o 53i" />""", file=routes)
        vehNr = 0
        for i in range(N):
            if random.uniform(0, 1) < pWE:
                print('    <vehicle id="right_%i" type="typeWE" route="right" depart="%i" />' % (
                    vehNr, i), file=routes)
                vehNr += 1
            if random.uniform(0, 1) < pEW:
                print('    <vehicle id="left_%i" type="typeWE" route="left" depart="%i" />' % (
                    vehNr, i), file=routes)
                vehNr += 1
            if random.uniform(0, 1) < pNS:
                print('    <vehicle id="down_%i" type="typeNS" route="down" depart="%i" color="1,0,0"/>' % (
                    vehNr, i), file=routes)
                vehNr += 1
        print("</routes>", file=routes)

# The program looks like this
#    <tlLogic id="0" type="static" programID="0" offset="0">
# the locations of the tls are      NESW
#        <phase duration="31" state="GrGr"/>
#        <phase duration="6"  state="yryr"/>
#        <phase duration="31" state="rGrG"/>
#        <phase duration="6"  state="ryry"/>
#    </tlLogic>


def run():
    """execute the TraCI control loop"""
    step = 0
    # we start with phase 2 where EW has green
    traci.trafficlight.setPhase("0", 2)
    while traci.simulation.getMinExpectedNumber() > 0:
        traci.simulationStep()
        if traci.trafficlight.getPhase("0") == 2:
            # we are not already switching
            if traci.inductionloop.getLastStepVehicleNumber("0") > 0:
                # there is a vehicle from the north, switch
                traci.trafficlight.setPhase("0", 3)
            else:
                # otherwise try to keep green for EW
                traci.trafficlight.setPhase("0", 2)
        step += 1
    traci.close()
    sys.stdout.flush()


def get_options():
    optParser = optparse.OptionParser()
    optParser.add_option("--nogui", action="store_true",
                         default=False, help="run the commandline version of sumo")
    options, args = optParser.parse_args()
    return options


# this is the main entry point of this script
if __name__ == "__main__":
    options = get_options()

    # this script has been called from the command line. It will start sumo as a
    # server, then connect and run
    if options.nogui:cr
        sumoBinary = checkBinary('sumo')
    else:
        sumoBinary = checkBinary('sumo-gui')

    # first, generate the route file for this simulation
    generate_routefile()

    # this is the normal way of using traci. sumo is started as a
    # subprocess and then the python script connects and runs
    traci.start([sumoBinary, "-c", "cross.sumocfg",
                             "--tripinfo-output", "tripinfo.xml"])
    run()

cross.sumocfg及其相关文件如下,把这些文件复制到本地,存为以下文件名,即可运行,前提是你的环境变量配置没有问题。
相关仿真文件
文件链接如下:
链接:https://pan.baidu.com/s/1IFs4UJUBPxPM_LUTSrcmSw
提取码:Sumo

欢迎交流!

### 关于SUMO的IT技术相关介绍 #### 1. **SUMO概述** Eclipse SUMO(Simulation of Urban MObility)是一款开源的城市交通模拟软件,广泛应用于城市交通规划、分析以及自动驾驶等领域。它提供了全面的功能集,能够灵活配置各种交通场景,并适用于多种实际应用需求[^2]。 #### 2. **功能特点** - **灵活性**: 用户可以通过定义不同的参数来调整路网结构、车辆行为和交通流量。 - **扩展性**: 支持与其他工具集成,例如通过Gym库与强化学习框架Stable Baselines 3 (SB3) 结合,实现复杂的交通决策任务,如换道策略优化[^1]。 - **适用性强**: 不仅可以用于微观交通仿真,还可以处理宏观层面的交通流建模。 #### 3. **核心技术路线** 一种常见的技术路径是将SUMOPython结合使用,借助TraCI接口完成动态交互操作。例如,在交叉口信号灯自适应控制的研究中,利用Python脚本实时读取交通数据并更新信号配时方案[^3]。 #### 4. **应用场景拓展** 除了基本的交通仿真外,SUMO还被用来解决更复杂的问题领域,比如车联网环境下的通信协议测试和技术挑战应对。特别是在 VANETs 中涉及的移动模型设计方面,SUMO 提供了一个理想的实验平台[^4]。 ```python import traci import sumolib def run_simulation(): step = 0 while step < 1000: traci.simulationStep() vehicles = traci.vehicle.getIDList() # 获取当前所有车辆ID列表 for vehicle_id in vehicles: lane_index = traci.vehicle.getLaneIndex(vehicle_id) # 查询某辆车所在车道索引号 speed = traci.vehicle.getSpeed(vehicle_id) # 获得该车速度值 step += 1 if __name__ == "__main__": sumoBinary = "sumo-gui" sumoCmd = [sumoBinary, "-c", "path/to/your/config/file.sumocfg"] traci.start(sumoCmd) try: run_simulation() finally: traci.close() ``` 上述代码片段展示了如何启动一个简单的SUMO仿真过程并通过TraCI获取部分运行期间的数据样本。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值