基于sumo实现交通灯控制算法的模板

基于sumo实现交通灯控制算法的模板

目录

  • 在windows安装
  • run hello world
    • network
    • routes
    • viewsettings & configuration
    • simulation
  • 交通灯控制系统
    • 介绍
    • 文件生成器类(FileGenerator)
    • 道路网络(Network)
    • 辅助函数
    • 生成道路网络(GenerateNetwork)
    • 生成路径(route)
    • 生成车辆(vehicle)
    • 生成交通信号灯(tlLogic)
    • 生成探测器(detector)
    • py程序接口(TraCI)
  • 附录
    • node
    • edge
    • connection
    • route
    • vehicle
    • tlLogic
    • TraCI
    • Detector
    • simulation
    • 参考资料
    • 有关文件

原文地址:https://www.wolai.com/7SsvyQLdZQr5TPikSDG9rR

代码在附录中

在windows安装

SUMO 软件包中的大多数应用程序都是命令行工具,目前只有sumo-gui和netedit不是。

SUMO 应用程序是普通的可执行文件。你只需在命令行中输入其名称即可启动它们;例如,netgenerate的调用方式是

netgenerate.exe

这只是启动应用程序(本例中为netgenerate)。由于没有给出参数,应用程序不知道要做什么,只能打印有关自身的信息:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

SUMO 中有两个gui程序:

  • netedit:生成network、routes等
  • sumo-gui:执行simulation

这两个程序均可通过命令行启动:

启动netedit:

netedit

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

启动sumo-gui:

sumo-gui

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

run hello world

通过GUI创建和仿真的详细操作参考此处:https://sumo.dlr.de/docs/Tutorials/Hello_World.html

我们接下来要讨论的是通过文件创建和仿真,这将用到如下文件:

  • *.nod.xml:记录节点信息
  • *.edg.xml:记录边信息
  • *.net.xml:记录网络信息,通过 netconvert 生成
  • *.rou.xml:记录车辆信息
  • *.settings.xml:记录仿真界面的配置信息
  • *.sumocfg:记录仿真信息,sumo通过此文件执行仿真

network

所有节点都有一个位置(x 坐标和 y 坐标,描述到原点的距离,以米为单位)和一个 ID,以供将来参考。因此,我们的简单节点文件如下:

<nodes>
    <node id="1" x="-250.0" y="0.0" />
    <node id="2" x="+250.0" y="0.0" />
    <node id="3" x="+251.0" y="0.0" />
</nodes>

您可以使用自己选择的文本编辑器编辑文件,并将其保存为hello.nod.xml,其中.nod.xml是 Sumo 节点文件的默认后缀。

现在我们用边来连接节点。这听起来很简单。我们有一个源节点 ID、一个目标节点 ID 和一个边 ID,以备将来参考。边是有方向的,因此每辆车在这条边上行驶时,都会from给出的源节点开始,在给出的to节点结束。

<edges>
    <edge from="1" id="1to2" to="2" />
    <edge from="2" id="out" to="3" />
</edges>

将这些数据保存到名为hello.edg.xml 的文件中。

现在我们有了节点和边,就可以调用第一个 SUMO 工具来创建网络了。 确保netconvert位于PATH中的某个位置,然后调用

netconvert --node-files=hello.nod.xml --edge-files=hello.edg.xml --output-file=hello.net.xml

这将生成名为hello.net.xml 的网络。

启动netedit并查看文件:

netedit hello.net.xml

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

routes

更多信息请参阅"车辆、车辆类型和路线的定义"

定义如下几个字段:

  • vType :车辆类型的信息
  • route :路径的信息
  • vehicle :车辆的信息

如下所示的hello.rou.xml文件:

<routes>
    <vType id="typeCar" accel="0.8" decel="4.5" sigma="0.5" length="5" minGap="2.5" maxSpeed="16.67" guiShape="passenger"/>
    <route id="route0" edges="1to2 out"/>
    <vehicle depart="1" id="veh0" route="route0" type="typeCar" />
    <vehicle depart="20" id="veh1" route="route0" type="typeCar" />
</routes>


注意:定义多辆车时,应该按照depart属性排序

viewsettings & configuration

使用图形用户界面进行模拟时,添加一个 gui-settings 文件非常有用,这样就不必在启动程序后更改设置。为此,创建一个viewsettings文件:

<viewsettings>
    <viewport y="0" x="250" zoom="100"/>
    <delay value="100"/>
</viewsettings>

将其保存为配置文件中包含的名称,在本例中就是hello.settings.xml

在这里,我们使用视口(viewport)来设置摄像机的位置,并使用延迟(delay)来设置模拟的每一步之间的延迟(毫秒)。

现在,我们将所有内容粘合到一个配置文件中:

<configuration>
    <input>
        <net-file value="hello.net.xml"/>
        <route-files value="hello.rou.xml"/>
        <gui-settings-file value="hello.settings.xml"/>
    </input>
    <time>
        <begin value="0"/>
        <end value="10000"/>
    </time>
</configuration>

将其保存到hello.sumocfg

simulation

Using the Command Line Applications - SUMO Documentation (dlr.de)

我们就可以开始模拟了,方法如下:

sumo-gui -c hello.sumocfg

交通灯控制系统

看不懂的参数请看附录

介绍

Quick Start (old style) - SUMO Documentation (dlr.de)

我们的目的是生成如下类型的道路网络:

  • 十字路口的规模是可自定义的
  • 十字路口的道路是有专用转向车道的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

道路网络network:

  • 节点node
  • 边edge
  • 道路lane:每条边对应多条道路
  • 连接connection:边与边之间的连接关系

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们的项目按照如下流程进行:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

文件生成器类(FileGenerator)

import os
import subprocess
from sample.NetworkFileGenerator import NetworkFileGenerator
from sample.SumoFileGenerator import SumoFileGenerator


class FileGenerator:
    def __init__(self):
        self._networkGenerator = NetworkFileGenerator()
        self._sumoGenerator = SumoFileGenerator()
        self.network = None
        pass

    def GenerateAllFile(self, netconvert: str = "netconvert", cwd: str = "", name: str = "sample",
                        height: int = 1, width: int = 1, unity: int = 100,
                        avgCarAmount: int = 5, timePeriod: int = 100):
        if cwd == "":
            cwd = os.getcwd() + "/data"  # 输出目录
        # 生成所需文件
        self._networkGenerator.GenerateAllFile(cwd, name, width, height, unity)
        self._sumoGenerator.GenerateAllFile(cwd, name, self._networkGenerator.network, avgCarAmount, timePeriod)
        p = subprocess.Popen([netconvert,
                              "-c", "%s.netccfg" % (name),
                              "--no-turnarounds.tls", "true"],
                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                             cwd=cwd)
        p.wait()
        self.network = self._networkGenerator.network
        pass

    pass


  • 负责根据参数生成绝大多数有关文件
  • 支持输出目录的自定义
  • 支持输出文件名的自定义
  • 外界通过调用GenerateAllFile以使用该类

道路网络(Network)

道路网络的数据结构:

from collections import defaultdict


class Network:
    def __init__(self):
        """
        Node: (int, int)
        Edge: (Node, Node)
        Connection: (Node, Node, Node, lane: int)
        """
        self.width = 1  # 水平方向的交通灯数量
        self.height = 1  # 竖直方向的交通灯数量
        self.nodes = []  # 节点
        self.edges = []  # 边
        self.connections = []  # 连接

        self.tlNodes = []  # 交通灯节点
        self.boundaryNodes = []  # 边界节点
        self.inEdges = defaultdict(list)  # 入边表,Node -> [Edge]
        self.outEdges = defaultdict(list)  # 出边表,Node -> [Edge]
        pass

    pass

  • 节点使用二维坐标来描述
  • 边使用两个节点来描述
  • 连接使用三个节点来描述
  • width、height是交通灯的数量信息

辅助函数

def GetNodeId(i: int, j: int) -> str:
    return "%01d%01d" % (i, j)


def GetEdgeId(i: int, j: int, u: int, v: int) -> str:
    # from (i, j) to (u, v)
    return "%sto%s" % (GetNodeId(i, j), GetNodeId(u, v))


def GetRouteId(i: int, j: int, u: int, v: int, additional: int) -> str:
    # from (i, j) to (u, v)
    return "%s_%08d" % (GetEdgeId(i, j, u, v), additional)


def GetLaneId(i: int, j: int, u: int, v: int, lane: int) -> str:
    # from (i, j) to (u, v)
    return "%s_%1d" % (GetEdgeId(i, j, u, v), lane)


def GetDetectorId(i: int, j: int, u: int, v: int, lane: int) -> str:
    # from (i, j) to (u, v)
    return "det_%s" % (GetLaneId(i, j, u, v, lane))


def IsTrafficLightNode(width: int, height: int, i: int, j: int) -> bool:
    # [1, width] * [1, height] 范围内是交通灯节点
    return 1 <= i and i <= width and 1 <= j and j <= height


def IsBoundaryNode(width: int, height: int, i: int, j: int) -> bool:
    # [1, width] * [1, height] 范围外的一圈是边界
    return i == 0 or i == width + 1 or j == 0 or j == height + 1


def IsIllegalNode(width: int, height: int, i: int, j: int) -> bool:
    # [0, width + 1] * [0, height + 1] 范围外是非法的
    return i < 0 or i > width + 1 or j < 0 or j > height + 1


def IsCornerNode(width: int, height: int, i: int, j: int) -> bool:
    # (0, 0) (width + 1, 0) (0, height + 1) (width + 1, height + 1) 是角落
    return i == 0 and j == 0 or \
        i == width + 1 and j == 0 or \
        i == 0 and j == height + 1 or \
        i == width + 1 and j == height + 1


def GetEdgesOfRoute(path: list) -> str:
    # 从节点列表,以字符串形式,给出途经的边
    ret = ""
    for i in range(1, len(path)):
        ret += GetEdgeId(*path[i - 1], *path[i]) + " "
    return ret


def ToXMLElement(name: str, *arg: str):
    import xml.dom
    doc = xml.dom.minidom.Document()
    # doc = xml.dom.minidom.Document()
    element = doc.createElement(name)
    for i in range(1, len(arg), 2):
        element.setAttribute(arg[i - 1], arg[i])
    return element
    pass


  • [1, width] * [1, height]是交通灯的坐标
  • [1, width] * [1, height] 范围外的一圈是边界
  • [0, width + 1] * [0, height + 1] 范围外是非法的
  • (0, 0) (width + 1, 0) (0, height + 1) (width + 1, height + 1) 是角落

生成道路网络(GenerateNetwork)

  • 规定方向编号:参考极坐标系,角度与方向编号有线性关系
    • 0:x轴正向
    • 1:y轴正向
    • 2:x轴负向
    • 3:y轴负向
  • 规定转向编号:即方向编号的差分量
    • -1:右转
    • 0:直行
    • 1:左转

这样规定转向编号的原因是,转向编号与sumo的车道编号相对应。sumo的车道编号是从右到左的。

代码如下:

class NetworkFileGenerator:
    def __init__(self):
        self.cwd = None  # 输出目录
        self.name = None  # 文件名
        self.network = None  # 道路网络
        self._unity = None  # 单位长
        pass
        
    def GenerateNetwork(self, width: int, height: int) -> Network:
        self.network = Network()
        self.network.width = width
        self.network.height = height
        dx = [1, 0, -1, 0]
        dy = [0, 1, 0, -1]
        turn = [-1, 0, 1]  # 车道编号 -> 转向编号,分别对应:右转,直行,左转
        for i in range(width + 2):
            for j in range(height + 2):
                # 生成节点 (i, j)
                # 角落不需要生成
                if Utils.IsCornerNode(width, height, i, j):
                    continue
                node1 = (i, j)
                self.network.nodes.append(node1)
                if Utils.IsTrafficLightNode(self.network.width, self.network.height, i, j):
                    self.network.tlNodes.append(node1)
                else:
                    self.network.boundaryNodes.append(node1)
                pass

                for dir in range(len(dx)):
                    u = i + dx[dir]
                    v = j + dy[dir]
                    # 生成边 (i, j)->(u, v)
                    # 排除非法节点
                    if Utils.IsIllegalNode(width, height, u, v):
                        continue
                    # 角落不需要生成
                    if Utils.IsCornerNode(width, height, u, v):
                        continue
                    # 边界节点与边界节点互不相连,排除
                    if Utils.IsBoundaryNode(width, height, i, j) and Utils.IsBoundaryNode(width, height, u, v):
                        continue
                    # 生成边
                    node2 = (u, v)
                    edge = (node1, node2)
                    self.network.edges.append(edge)
                    self.network.outEdges[node1].append(edge)
                    self.network.inEdges[node2].append(edge)
                    pass

                    for lane in range(len(turn)):
                        dir2 = (dir + turn[lane] + len(dx)) % len(dx)
                        x = u + dx[dir2]
                        y = v + dy[dir2]
                        # (i, j)->(u,v)->(x,y)
                        # 排除非法的
                        if Utils.IsIllegalNode(width, height, x, y):
                            continue
                        # 角落不需要生成
                        if Utils.IsCornerNode(width, height, x, y):
                            continue
                        # 边界节点与边界节点互不相连
                        if Utils.IsBoundaryNode(width, height, u, v) and Utils.IsBoundaryNode(width, height, x, y):
                            continue
                        # 生成连接
                        node3 = (x, y)
                        connection = (node1, node2, node3, lane)
                        self.network.connections.append(connection)
                        pass
                    pass
                pass
            pass
        return self.network


生成路径(route)

SUMO Road Networks - SUMO Documentation (dlr.de)

我们使用回溯算法生成所有可能的路径。

由于该算法的时间开销较大,如果地图大小超过4*4,那么建议导入路径而不是生成

import xml.dom
import numpy as np
import Utils
from Network import Network
from collections import defaultdict

from sample.Utils import _GetEdgesOfRoute


class SumoFileGenerator:
    def __init__(self):
        self.cwd = None  # 输出目录
        self.name = None  # 文件名
        self.network = None  # 道路网络

        # for dfs
        self._visit = None
        self._path = None
        self._ans = None
        pass

    def _dfsrc(self, nodeP: tuple or None, nodeU: tuple):
        # 深度优先搜索递归核心 Depth First Search Recursive Core
        if nodeU in self.network.boundaryNodes and nodeP is not None:
            self._ans.append([x for x in self._path])
            return
        for _, nodeV in self.network.outEdges[nodeU]:
            if self._visit[nodeV] is True:
                continue
            self._visit[nodeV] = True
            self._path.append(nodeV)
            self._dfsrc(nodeU, nodeV)
            self._path.pop()
            self._visit[nodeV] = False
            pass

    def _GetRoutes(self, nodeU: tuple) -> list:
        # 生成所有以 nodeU 为起点的路径
        self._visit = defaultdict(bool)
        self._path = []
        self._ans = []
        self._visit[nodeU] = True
        self._path.append(nodeU)
        self._dfsrc(None, nodeU)
        return self._ans
        pass

    def _GenerateRouteFile(self, avgCarAmount, timePeriod):
        //...
    pass

生成车辆(vehicle)

用分布来模拟车辆到达,实际上是在采样。因为各个样本点独立同分布

设随机变量X是车辆到达的数量,P{X=k}是有k辆车到达的概率。

我们采取timePeriod个样本,各个样本就对应了各个时刻车辆的到达情况。

    def _GenerateRouteFile(self, avgCarAmount, timePeriod):
        // ...
        # 创建车辆
        arrivals = np.random.poisson(avgCarAmount, timePeriod)
        vehicleId = 0
        for time in range(len(arrivals)):
            for i in range(arrivals[time]):
                rootElement.appendChild(Utils.ToXMLElement(
                    "vehicle",
                    "id", "%08d" % (vehicleId),
                    "type", "typeCar",
                    "route", routeIds[np.random.randint(0, len(routeIds))],
                    "depart", "%d" % (time),
                ))
                vehicleId += 1
                pass
        // ...
            pass

生成交通信号灯(tlLogic)

直接遍历network中的交通灯节点,然后生成对应的XML元素,其中:

  • id是节点id
  • programID是随便填的
  • 相位暂时使用默认相位,以进行测试
    def _GenerateDefaultPhases(self) -> list:
        ret = []
        phase = "ggggrrgrrgrr"
        for i in range(4):
            ret.append(("17", phase))
            ret.append(("3", phase.replace("g", "y")))
            phase = phase[3:] + phase[:3]
        return ret
        pass
        
    def _GenerateTrafficLightFile(self):
        # *.add.xml,
        # 创建一个XML文档对象
        doc = xml.dom.minidom.Document()
        rootElement = doc.createElement("additional")  # 根节点
        doc.appendChild(rootElement)

        defaultPhases = self._GenerateDefaultPhases()  # 使用默认相位进行测试
        # attribute = ["id", "type", "programID", "offset"]
        for node in self.network.tlNodes:
            # 遍历交通灯节点
            TLElement = doc.createElement("tlLogic")
            rootElement.appendChild(TLElement)
            TLElement.setAttribute("id", Utils.GetNodeId(*node))
            TLElement.setAttribute("type", "static")
            TLElement.setAttribute("programID", "runner")
            TLElement.setAttribute("offset", "0")
            # 交通灯的相位
            for duration, state in defaultPhases:
                phaseElement = doc.createElement("phase")
                phaseElement.setAttribute("duration", duration)
                phaseElement.setAttribute("state", state)
                TLElement.appendChild(phaseElement)

        with open("%s/%s.add.xml" % (self.cwd, self.name), "w") as fileOut:
            fileOut.write(doc.toprettyxml())
        pass

生成探测器(detector)

为了使探测器能覆盖整条道路,我们只填入pos属性,而不填入endPos或length属性。

    def _GenerateDetectorFile(self):
        # *.det.xml,
        # 创建一个XML文档对象
        doc = xml.dom.minidom.Document()
        rootElement = doc.createElement("additional")  # 根节点
        doc.appendChild(rootElement)
        # attribute = ["id", "lane", "pos", "file", "friendlyPos"]
        for (i, j), (u, v) in self.network.edges:
            for lane in range(3):
                rootElement.appendChild(Utils.ToXMLElement(
                    "laneAreaDetector",
                    "id", Utils.GetDetectorId(i, j, u, v, lane),
                    "lane", Utils.GetLaneId(i, j, u, v, lane),
                    "pos", "0",
                    # "endPos", "100",
                    # "length", "%d" % (72.80),
                    "file", "%s/%s.out.xml" % (self.cwd, self.name),
                    "friendlyPos", "true", ))

        with open("%s/%s.det.xml" % (self.cwd, self.name), "w") as fileOut:
            fileOut.write(doc.toprettyxml())
        pass

py程序接口(TraCI)

TraCI 采用基于 TCP 的客户端/服务器架构来访问sumo。因此,使用附加命令行选项启动时,sumo将充当服务器:–remote-port <INT>,其中 是sumo用于监听传入连接的端口。

当使用 –remote-port<INT>选项启动时,sumo只准备模拟,等待所有外部应用程序连接并接管控制权。请注意,当sumo作为 TraCI 服务器运行时,–end <TIME>选项将被忽略。

使用sumo-gui作为服务器时,在处理 TraCI 命令之前,必须通过使用播放按钮或设置选项 –start来启动模拟。

import os
import sys
from FileGenerator import FileGenerator
from Network import Network

try:
    sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', "tools"))  # tutorial in tests
    sys.path.append(os.path.join(os.environ.get("SUMO_HOME", os.path.join(
        os.path.dirname(__file__), "..", "..", "..")), "tools"))  # tutorial in docs
    sys.path.append("/usr/local/Cellar/sumo/1.2.0/share/sumo/tools")
    from sumolib import checkBinary  # noqa
except ImportError:
    sys.exit("please declare environment variable 'SUMO_HOME' as the root directory of your sumo installation"
             "(it should contain folders 'bin', 'tools' and 'docs')")

import traci


# ====================================================================================================


# adapted from SUMO tutorials
def run(network: Network):
    """execute the TraCI control loop"""
    # step = 0
    # amber = 0
    # waits = []
    # phase = [0, 0, 0, 0, 0, 0, 0, 0, 0]
    # for i in range(0, NUM_JUNCTIONS):
    #     waits.append([0] * len(PHASES))
    cnt = 0
    while traci.simulation.getMinExpectedNumber() > 0:  # step <= 900:
        traci.simulationStep()
        traci.trafficlight.setPhase("11", cnt % 2)
        traci.trafficlight.setPhase("22", cnt % 2)
        cnt = cnt + 1

        # if step % PHASE_LENGTH == 0:
        #     for i in range(0, NUM_JUNCTIONS):
        #         if MAX_WAIT in waits[i]:
        #             phase[i] = waits[i].index(MAX_WAIT)
        #         else:
        #             if noPhaseChange(phase[i], i) != True:
        #                 phase[i] = backPressure(i)
        #                 amber = amber + 1
        #         traci.trafficlight.setPhase("0" + getNodeId(i), phase[i])
        #         for j in range(0, len(PHASES), 2):
        #             if j == phase[i]:
        #                 waits[i][j] = 0
        #             else:
        #                 if waits[i][j] < MAX_WAIT:
        #                     waits[i][j] += 1
        # step += 1
        # logging.warning(amber)
    traci.close()
    sys.stdout.flush()


if __name__ == '__main__':
    # const
    CWD = os.getcwd() + "/data"
    NAME = "sample"
    OUTPUTDIR = os.getcwd() + "/output"
    NETCONVERT = checkBinary('netconvert')
    SUMO = checkBinary('sumo-gui')

    # main
    generator = FileGenerator()
    generator.GenerateAllFile(NETCONVERT, CWD, NAME,
                              2, 2, 100,
                              2, 10)  # 生成文件
    print("GenerateAll finish")
    traci.start(
        [SUMO,
         "-c", "%s/%s.sumocfg" % (CWD, NAME),
         "--tripinfo-output", "%s/%s.tripinfo.xml" % (OUTPUTDIR, NAME),
         "--summary", "%s/%s.sum.xml" % (OUTPUTDIR, NAME)])
    run(generator.network)


附录

node

PlainXML - SUMO Documentation (dlr.de)

nod的属性:

属性名称类型说明
idid (string)节点名称
xfloat节点在平面上的 x 位置,以米为单位
yfloat节点在平面上的 y 轴位置,以米为单位
zfloat节点在平面上的 Z 位置,以米为单位
typeenum ( “priority”, “traffic_light”……)节点的可选类型

edge

PlainXML - SUMO Documentation (dlr.de)

edge的属性:

属性名称类型说明
idid (string)边的 ID(必须唯一)
fromreferenced node idThe name of a node within the nodes-file the edge shall start at
toreferenced node idThe name of a node within the nodes-file the edge shall end at
typereferenced type idThe name of a type within the SUMO edge type file

connection

PlainXML - SUMO Documentation (dlr.de)

SUMO Road Networks - SUMO Documentation (dlr.de)

connection的属性:

名称类型说明
fromedge id (string)开始连接的输入边 ID
toedge id (string)连接结束时出线边的 ID
fromLaneindex (unsigned int)开始连接的输入边的车道
toLaneindex (unsigned int)连接结束时出线边缘的车道

route

Definition of Vehicles, Vehicle Types, and Routes - SUMO Documentation (dlr.de)

route 的属性:

属性名称价值类型说明
idid (string)路线名称
edgesid list车辆应行驶的路线,以 ID 表示,用空格隔开

vehicle

Definition of Vehicles, Vehicle Types, and Routes - SUMO Documentation (dlr.de)

vType 的属性:

属性名称价值类型默认值说明
idid (string)-车辆类型名称
accelfloat2.6此类车辆的加速能力(单位:m/s^2)
decelfloat4.5此类车辆的减速能力(单位:m/s^2)
sigmafloat0.5汽车跟随模型参数,见下文
lengthfloat5.0车辆长度(米)
minGapfloat2.5最小车距(米)
maxSpeedfloat55.55(200 km/h),车辆的最大速度(米/秒)
guiShapeshape (enum)“unknown”绘制车辆形状。默认情况下,绘制的是标准客车车身。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

vehicle 的属性:

属性名称价值类型说明
idstring车辆名称
typestring该车辆使用的车辆类型 ID
routestring车辆行驶路线的 ID
departfloat(s)车辆进入网络的时间步长

tlLogic

Traffic Lights - SUMO Documentation (dlr.de)

tlLogic 的属性:

属性名称价值类型说明
idid (string)交通信号灯的 id。必须是 .net.xml 文件中已有的交通信号灯 id。交通信号灯的 id 通常与路口 id 相同。名称可通过右键单击受控路口前的红/绿条获得。
typeenum (static, actuated, delay_based)交通信号灯的类型(固定相位持续时间、基于车辆间时间间隔的相位延长(驱动式)或基于排队车辆累积时间损失的相位延长(基于延迟式) )
programIDid (string)交通灯程序的 id;必须是交通灯 id 的新程序名称。请注意,"off "为保留名,见下文。
offsetint程序的初始时间偏移

phase 的属性:

属性名称价值类型说明
durationtime (int)阶段的持续时间
statelist of signal states该阶段的红绿灯状态如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于控制单个交叉路口的交通信号灯,由 netconvert 生成的默认指数以顺时针方式编号,从 12 点钟方向的 0 开始,右转顺序在直行和左转之前。人行横道总是被分配在最后,也是按顺时针方向。

如果将交通信号灯连接起来,由一个程序控制多个交叉路口,则每个交叉路口的排序保持不变,但指数会根据输入文件中受控路口的顺序增加。

例如:ggrgrrrggrrg对应:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

TraCI

TraCI - SUMO Documentation (dlr.de)

Detector

Detector - SUMO Documentation (dlr.de)

Lanearea Detectors (E2) - SUMO Documentation (dlr.de)

Attribute NameValue TypeDescription
idid (string)A string holding the id of the detector
lanereferenced lane idThe id of the lane the detector shall be laid on. The lane must be a part of the network used. This argument excludes the argument lanes.
posfloatThe position on the first lane covered by the detector. See information about the same attribute within the detector loop description for further information. Per default, the start position is placed at the first lane’s begin.
endPosfloatThe end position on the last lane covered by the detector. Per default the end position is placed at the last lane’s end.
lengthfloatThe length of the detector in meters. If the detector reaches over the lane’s end, it is extended to preceding / consecutive lanes.
filefilenameThe path to the output file. The path may be relative.
friendlyPosboolIf set, no error will be reported if the detector is placed behind the lane. Instead, the detector will be placed 0.1 meters from the lane’s end or at position 0.1, if the position was negative and larger than the lane’s length after multiplication with -1; default: false.

simulation

参考资料

SUMO官方文档

SUMO学习入门(一)SUMO介绍 - 知乎 (zhihu.com)

SUMO 从入门到基础 SUMO入门一篇就够了_sumo文档-CSDN博客

XML - Wikipedia

有关文件

windows安装包:

sumo-win64-1.19.0.msi

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/297308.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年阿里云优惠活动清单_优惠代金券领取大全

阿里云服务器优惠活动大全包括&#xff1a;云服务器新人特惠、云小站、阿里云免费中心、学生主机优惠、云服务器精选特惠、阿里云领券中心等&#xff0c;活动上阿里云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;…

Servlet 3.0的异步处理

1、传统Servlet处理 Web容器会为每个请求分配一个线程&#xff0c;默认情况下&#xff0c;响应完成前&#xff0c;该线程占用的资源都不会被释放。若有些请求需要长时间(例如长处理时间运算、等待某个资源)&#xff0c;就会长时间占用线程所需资源&#xff0c;若这类请求很多&…

L1-078:吉老师的回归

题目描述 曾经在天梯赛大杀四方的吉老师决定回归天梯赛赛场啦&#xff01; 为了简化题目&#xff0c;我们不妨假设天梯赛的每道题目可以用一个不超过 500 的、只包括可打印符号的字符串描述出来&#xff0c;如&#xff1a;Problem A: Print "Hello world!"。 众所周知…

Python基础入门第七课笔记(自定义函数 define)

函数 函数必须先定义再调用 函数必须先定义再调用 函数必须先定义再调用 定义函数&#xff1a; def 函数名&#xff08;形参&#xff09;&#xff1a; 代码1 代码2 ………. 调用函数&#xff1a; 函数名&#xff08;实参&#xff09; 形参&…

【AI视野·今日CV 计算机视觉论文速览 第281期】Tue, 2 Jan 2024

AI视野今日CS.CV 计算机视觉论文速览 Tue, 2 Jan 2024 Totally 95 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computer Vision Papers Refining Pre-Trained Motion Models Authors Xinglong Sun, Adam W. Harley, Leonidas J. Guibas考虑到在视频中手动注释运…

分布式(6)

目录 26.雪花算法如何实现的&#xff1f; 27.雪花算法有什么问题&#xff1f;有哪些解决思路&#xff1f; 28.有哪些方案实现分布式锁&#xff1f; 29.基于数据库如何实现分布式锁&#xff1f;有什么缺陷&#xff1f; 30.基于Redis如何实现分布式锁&#xff1f;有什么缺陷&…

LIDAR激光雷达反射板

LIDAR&#xff08;Light Detection And Ranging&#xff09;系统是一种集激光、全球定位系统&#xff08;GPS&#xff09;和惯性导航系统&#xff08;INS&#xff09;三种技术于一身的系统&#xff0c;用于获得点云数据并生成精确的数字化三维模型。 LIDAR系统包括一个单束窄带…

Pycharm打包程序为exe文件

Pycharm打包程序为exe文件 【一】导入模块pyinstaller 【1】图片说明 【2】文字说明 根据图片顺序执行 首先点击file进入settings界面&#xff0c;在setting界面找到Project下面的Python Interpretor&#xff0c;点击号进行模块的添加在搜索框中输入pyinstaller&#xff0c;…

【Proteus仿真】【Arduino单片机】水箱液位监控系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用LCD1602液晶、按键、蜂鸣器、液位传感器、ADC转换器、水泵等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示当前水位、上下限阈…

正交投影矩阵与透视投影矩阵的推导

正交投影矩阵 正交投影矩阵的视锥体是一个长方体 [ l , r ] [ b , t ] [ f , n ] [l,r][b,t][f,n] [l,r][b,t][f,n]&#xff0c;我们要把这个长方体转换到一个正方体 [ − 1 , 1 ] [ − 1 , 1 ] [ − 1 , 1 ] [-1,1][-1,1][-1,1] [−1,1][−1,1][−1,1]中&#xff0c;如下图所…

【KD】知识蒸馏(knowledge distillation)简单介绍

最近学到了知识蒸馏的相关知识&#xff0c;来简单总结一下૮꒰ ˶• ༝ •˶꒱ა。 知识蒸馏 知识蒸馏&#xff0c;是一种模型压缩的手段。通过训练学生模仿教师的行为&#xff0c;将嵌入在大的教师模型中的知识迁移到小的学生模型。 例如&#xff0c;TinyBERT(Jiao et al.,2…

C++结合OpenCV:图像的基本表示方法

1.二值图像 二值图像是指仅仅包含黑色和白色两种颜色的图像。在计算机中&#xff0c;通过一个栅格状排列的数据集&#xff08;矩阵&#xff09;来表示和处理图像。例如&#xff0c;图1是一个字母A的图像&#xff0c;计算机在处理该图像时&#xff0c;会首先将其划分为一个个的小…

Mysql show Profiles详解

1.简介 show profile 和 show profiles 命令用于展示SQL语句的资源使用情况&#xff0c;包括CPU的使用&#xff0c;CPU上下文切换&#xff0c;IO等待&#xff0c;内存使用等&#xff0c;这个命令对于分析某个SQL的性能瓶颈非常有帮助&#xff0c;借助于show profile的输出信息&…

jenkins+selenium+python实现web自动化测试

jenkinsselenium可以做到对web自动化的持续集成。 Jenkins的基本操作&#xff1a; 一、新建视图及job 新建视图&#xff1a; 新建job&#xff1a; 可以选择构建一个自由风格的软件项目或者复制已有的item 二、准备工作&#xff1a; 安装Jenkins插件&#xff0c;SSH plugin …

快速入门Visual Studio 2022开发.Net Framework研发环境指南

IDE工具 Visual Studio 2022 Vs2022企业版 - VisualStudioSetup.exe Visual Studio Code VSCodeUserSetup-x64-1.66.2.exeVSCodeUserSetup-x64-1.67.0-insider.exe IDE环境 编程字体YaHei.Consolas YaHei.Consolas.1.12.ttf IDE插件 Visual Studio Code常用插件 Chinese…

分布式锁3: zk实现分布式锁4 使用临时顺序节点+watch监听+可重入(threadLocal)

一 zk实现分布式锁的可重入性 1.1 使用ThreadLocal属性 引入ThreadLocal线程局部变量保证zk分布式锁的可重入性。 1.2 关键代码说明 1.3 代码 1.3.1 初始化客户端 1.3.2 分布式锁代码 package com.atguigu.distributed.lock.config;import com.baomidou.mybatisplus.core…

Java:Lambda表达式、方法引用

文章目录 1、Lambda表达式1.1 Lambda表达式体验1.2 Lambda表达式的省略形式1.3 Lambda表达式练习 2、方法引用体验3、方法引用符4、引用静态方法5、引用对象的实例方法6、引用类的实例方法7、引用构造方法8、引用数组的构造方法9、方法引用练习9.1 练习19.2 练习29.3 练习3 10、…

差分电路原理以及为什么输出电压要偏移

我们在使用放大器芯片的时候&#xff0c;除了对放大器芯片本身应用外&#xff0c;通常还需要搭建一些外围电路来满足放大器芯片的使用条件&#xff0c;最终满足应用的功能&#xff0c;下面通过一个差分电路来熟悉这些应用。 差分运算放大电路&#xff0c;对共模信号得到有效抑…

函数——系统函数2(c++)

这次主要就只有一个系统函数&#xff1a; &#xff08;注&#xff1a;a为变量名&#xff09; 名称 用法 用处 sqrt sqrt(a) 算出变量a的平方根 &#xff08;注&#xff1a;使用sqrt函数时&#xff0c;需要用到头文件 #i…

leetcode算法题之递归--综合练习(一)

此专题对我们之前所学的关于递归的内容进行一个整合&#xff0c;大家可以自行练习&#xff0c;提升自己的编码能力。 本章目录 1.找出所有子集的异或总和在求和2.全排列II3.电话号码的字母组合4.括号生成5.组合6.目标和7.组合总和8.字母大小写全排列9.优美的排列 1.找出所有子…
最新文章