网络构建过程

netconvertnetgeneratenetedit 共享相同的网络构建过程,该过程在读取数据后(在 netconvert 中)或在生成内部描述后(在 netgenerate 中)立即开始。

该过程要求至少给定节点和边,可选地还包括边和/或车道之间的连接以及其他可选信息。关于如何构建网络的提示——例如是否应添加掉头或高速公路匝道,是否应猜测交通灯或环岛等——均从选项中获取。

下面,您可以找到构建网络时执行的所有步骤的列表。可选步骤以斜体表示。

  1. 修改节点和边的集合
    1. 连接交叉口簇
    2. 移除自环
    3. 移除孤立道路
    4. 移除不需要的边
    5. 移除空节点和几何节点
    6. 连接相似的边
    7. 拆分几何边
    8. 猜测并设置匝道
  2. 将网络移至原点
  3. TLS(交通灯系统)位置计算
    1. 将节点分配给交通灯
    2. 连接交通灯节点
  4. 计算车道之间的连接
    1. 计算转弯方向
    2. 对节点的边进行排序
    3. 计算被接近的边
    4. 计算接近的车道
    5. 在被接近的车道上划分车道
    6. 附加掉头
    7. 重新检查车道末端
  5. 几何计算
    1. 计算节点形状
    2. 计算边形状
  6. 计算通行权和交通灯程序
    1. 计算 TLS 逻辑
    2. 计算节点逻辑
    3. 计算交通灯逻辑
  7. 完成内部边

这些计算步骤在 void NBNetBuilder::compute(OptionsCont &oc) 中执行。以下将更详细地描述这些步骤。

步骤#

  • 前置条件:所有输入已读取
  • 前置条件:节点具有:id、笛卡尔坐标、类型(可选,可能更改)
  • 前置条件:边具有:有效的起始/终止节点、车道数量、最大速度限制、允许的车辆类别、几何形状(可能更改)、typeID、车道分布信息、名称(可选)、优先级信息(可选)

#1: 修改节点和边的集合#

目的:从内部表示中移除不需要的边/节点;如果需要,添加几何节点 后置条件:所有不需要的元素(节点、边)被移除,如果需要则插入/移除几何节点,属性如上所述

执行以下子步骤:

  • joinJunctions('连接交叉口簇'):构建节点簇

    目的:连接形成单个交叉口的网络图节点。 后置条件:交叉口已连接,属性如上所述 影响:移除并添加节点,移除边,重新映射连接(待定) 状态:待定

  • removeSelfLoops('移除自环'):移除所有起始节点与终止节点相同的边

    后置条件:每条边都是两个不同节点之间的单向连接(确定) 状态:对我而言是绿色,但我不确定为什么要构建边列表然后提供给重新映射方法;在重新映射方法中检查连接是否存在是否足够?

  • joinSimilarEdges('连接相似的边'):连接连接相同节点的边

    后置条件:不存在两条具有相同几何形状且连接相同节点的边 状态:黄色,因为代码中有两个注释,一个是关于 bug,第二个是关于缺少对车辆类别的检查;应重新审视(为什么在这里,如果不这样做会发生什么) 注释:?之前,只有一条道路可以连接相同的交叉口;现在不是了。为什么,解释一下,它是如何工作的? 注释:此方法使用两个魔术数字来确定边是否“相似”: distanceThreshold = 7.; // 不要合并距离更远的边 lengthThreshold = 0.10; // 不要合并相对长度差异更大的边

  • removeIsolatedRoads('查找孤立道路'):移除孤立的边(不属于网络的一部分)

    后置条件:?未在某处定义 状态:黄色;该方法相当大,并且在 TLS 控制中没有移除边;它是如何工作的? 注释:应重新审视

  • removeUnwishedEdges('移除不需要的边'):移除不在 myEdges2Keep 中的边

    后置条件:不需要的边不再在内部容器中(确定) 状态:黄色;完整的 keep/remove/keep-postload - 内容应重新审视

  • removeUnwishedNodes('移除空节点和几何节点' 或 '移除空节点'):移除无用的节点

    后置条件:空节点、没有传入/传出边的节点被移除(确定) 后置条件:仅影响边几何形状的节点在需要时被移除(确定) 状态:黄色;应分两步进行以获得更清晰的代码;此外,我们曾遇到过 bug,即空的 acosta 节点仍在网络中;这解决了吗?

  • splitGeometry('拆分几何边'):在几何位置拆分边

    后置条件:如果需要,边仅具有线性几何形状 状态:黄色;构建的节点命名不当

  • Guessing on-/off-ramps猜测并设置匝道

    目的:添加缺失的匝道 状态:待定

作为结果,读取/生成的网络的内部表示包含用户想要的节点/边集合。

#2: 将网络移至原点#

目的:让网络坐标从 0,0 开始 状态:绿色

#3: TLS 位置计算#

目的:让节点知道它们是否由交通灯控制

  • guessTLs('将节点分配给交通灯')

    后置条件:空节点、没有传入/传出边的节点被移除(确定) 状态:待定

  • joinTLS('连接交通灯节点')

    后置条件:空节点、没有传入/传出边的节点被移除(确定) 状态:待定

#4: 连接计算#

目的:确定和/或分配交叉口之间车道的连接

计算转弯方向#

  • 代码: NBTurningDirectionsComputer::computeTurnDirections(...);
  • 后置条件: 边知道其掉头方向(如果存在)。
  • 原因: 掉头在后续步骤中与其他行驶方向的处理方式不同。
  • 方法

对于每条可能连接的传入边和传出边的组合,我们计算它们之间的角度。如果此角度 >160°,我们假设这可能是一个掉头。如果两条边以不同方向连接相同的两个节点,我们将此角度加上 360°。我们将带有角度的边对存储到一个按角度降序排序的列表中。计算完所有组合后,我们遍历该列表,并将首先看到的那些设置为掉头,标记传入和传出边都已被使用,以避免使用它们两次。如果一条边以 >360° 的角度出现两次——即多条边连接两个相同的节点——我们会发出警告。

  • 状态: 黄色

    连接检查应在此处省略,请参见内联文档 像往常一样,您可能会发现病态交叉口

对节点的边进行排序#

  • 代码: NBNodesEdgesSorter::sortNodesEdges(...);
  • 后置条件: 每个节点的边(传入、传出和所有边)按顺时针方向排序,从 12 点钟方向开始。具有相同角度的传入边在所有边的列表中位于相应的传出边之前。
  • 原因: 假设在后续计算步骤中给定此顺序
  • 方法

我们首先对节点的边向量(传入、传出、所有)进行排序。然后,我们遍历所有边的向量,如果传入边和传出边具有相同角度,并且传入边在传出边之后(使用 "isTurningDirection" 确定),则交换它们。

  • 状态: 黄色

    未针对左侧行驶网络进行验证 该方法使用方法 "NBEdge::isTurningDirectionAt(...)",这不是对先前执行的掉头计算的简单使用

计算节点类型#

  • 代码: NBNodeTypeComputer::computeNodeTypes(...);
  • 后置条件: 每个节点具有以下类型之一: NODETYPE_PRIORITY_JUNCTION, NODETYPE_RIGHT_BEFORE_LEFT, NODETYPE_TRAFFIC_LIGHT, NODETYPE_NOJUNCTION(?)。
  • 原因: 我们需要这个来计算通行权规则。
  • 方法

我们单独研究每个节点。首先检查一些特殊情况:

  • 如果类型已设置 (myType != NODETYPE_UNKNOWN) -> 跳过
  • 如果我们只有一条传入边 -> 设置为 NODETYPE_PRIORITY_JUNCTION
  • 如果是简单延续 -> 设置为 NODETYPE_PRIORITY_JUNCTION

首先,我们假设交叉口是 NODETYPE_RIGHT_BEFORE_LEFT 类型。然后我们遍历所有不相对的传入边组合。一旦我们遇到两条边之间的速度限制差异超过 10km/h(大约),我们将类型设置为 NODETYPE_PRIORITY_JUNCTION。如果其中一条边的速度限制超过 49km/h(我们使用此值以避免浮点问题),情况也是如此。

  • 状态: 黄色

    研究是否可以更早设置 NODETYPE_NOJUNCTION(由用户) 使用的方法 "getOppositeIncoming" 应重新验证

计算优先级#

  • 代码: NBEdgePriorityComputer::computeEdgePriorities(...);
  • 后置条件: 每条边在其起始和结束的节点处都有一个优先级。起始节点和终止节点处的优先级可能不同。边的优先级为 1(优先级较高)或 0(优先级较低或全部相等)。
  • 原因: 我们需要这个来计算通行权规则。
  • 方法

所有优先级初始化为 0。

  • 状态: 橙色

#5: 几何计算#

#6: 计算通行权和交通灯程序#

#7: 完成内部边(可选)#

旧版#

步骤 #9-#10: 计算特定信号/通行权#

步骤 #11-#17: 计算和设置车道到车道的连接#

步骤 #18-#19: 计算几何形状#

我目前关注的是边的形状,因为即使是 eworld 或 TrafficModeler 导出在调试模式下也在此处停止。它在 NBEdge::computeEdgeShape 中。(实际上,据我理解,这个方法是关于这条边的车道形状。)在此算法中,必须区分以下三种情况:

laneShapeIntersectsWithNodeShape.png 边的形状与节点形状相交。然后,形状被修剪到交点。这看起来相当合理。
laneShapeOutsideOfNodeShape.png 边的形状在节点形状之外。当前的算法外推边形状的最后一行,并将边扩大到新的交点。这对我来说也看起来很合理。
laneShapeInsideOfNodeShape.png 边的形状完全在节点形状内。这里应该发生什么?(红点显示了 netconvert 目前的做法。)

因此我想知道,在第三种情况下,netconvert 的正确行为应该是什么。

步骤 #20-#22: 计算通行权规则#

步骤 #23: 应用额外的偏移量#

表格#

操作 影响
节点 连接
调整输入 x x x
'构建交叉口簇' x x x
'移除自环' x x
'连接相似的边'
'查找孤立道路'
'移除不需要的边'
'移除空节点和几何节点' 或 '移除空节点'
'拆分几何边'
'猜测并设置匝道'
将网络移至原点
TLS 位置计算
将节点分配给交通灯
连接交通灯节点
计算车道之间的连接
计算转弯方向
对节点的边进行排序
计算被接近的边
计算接近的车道
在被接近的车道上划分车道
附加掉头(可选)
重新检查车道末端
几何计算
计算节点形状
计算边形状
计算通行权和交通灯程序
计算 TLS 逻辑
计算节点逻辑
计算交通灯逻辑
完成内部边(可选)