FASS 2.0 / scene.signal
MagCar 管控区排队、兼容组并行与扫车放行
本文说明 FASS 2.0 磁导航场景中,磁条交管进程如何根据管控区配置表对 MagCar(FASS 1.0 磁条车)进行停车等待、排队和放行。读者按本文即可完成十字路口、汇合点、单入口限流的配表,并理解扫车每一拍在做什么。
交管策略可以概括为四句话:
主键是管控触发站点。同一触发点多条启用记录只保留第一条。未启用(IsUse=false)的行保留在文件中但不参与判定。
| 字段 | JSON 键 | 含义与配法 |
|---|---|---|
| 管控触发站点 | TriggerSit | MagCar 必须停稳在此站点后才进入本行排队。应对齐现场停车点,不要把路口内部行驶点当成触发点。 |
| 管控区名称 | AreaName | 同名多行绑成一个路口,共用等待时长(取最长)。空则该触发点自成一区,相当于单入口限流。 |
| 兼容组 | CompatGroup | 同区里互不干扰的线路填不同组名(如东西 EW、南北 NS)。会交叉、会抢同一段路的填同组。空字符串与其他空组视为同组。 |
| 优先级 | Priority | 整数,越大越先放。干道高、支路低。只在冲突线路之间比较。 |
| 等待时长 | WaitSeconds | 秒。同区多行不一致时取最长。≤0 表示不做插队。用于防止支路被干道一直堵住。 |
| 管控区站点列表 | ControlArea | 本线路穿过路口的内部站点,逗号分隔,如 10,11。不要把各方向排队触发点写进来。空则回退为触发点本身。 |
| 区内最多几辆 | ControlCapacity | 本行容量。小于 1 按 1 处理。统计范围:占用本行内部站点的车 + 与本行冲突、已发启动但未进区的在途车。 |
| 放行后启停字节 | ControlReleaseStartStop | 兼容字段。MagCar 放行发 FASS 1.0 启动指令,不使用该字节。 |
| 启用 | IsUse | false 时本行不生效。 |
| 名称 | 说明 |
|---|---|
| 到达时刻 | 进程第一次扫到该 MagCar 停在该触发点的时间。开走后再回来重新计时。不写入 JSON。 |
| 在途占额 | 已对该车发过启动,但尚未占用本行内部站点。避免「刚放行、车还在触发点」时下一拍又放一辆冲突车。 |
| 参数 | 默认 | 说明 |
|---|---|---|
| TickMs | 1000 | 扫车周期(毫秒),下限按 200ms 夹紧。 |
| PendingTimeoutSeconds | 8 | 在途超时(秒)。超时后取消占额,防止启动失败把名额卡死。 |
| AreasPath | Config\Signal\mag-control-areas.json | 相对路径只解析 SimpleLite 工作目录,不读 plugins 目录。 |
进程启动或点「重新加载配置」后,读取启用规则。此后约每秒执行一次 ScanAndRelease。
状态不是「运行中 / Running」。下列视为可排队:停止中、充电中、WaitPass,以及没有 pendingLocks、没有 occupied 标签的非运行状态。充电中的车放行前会尝试 StopCharge。
对某一等待车辆,只统计占用该行 ControlArea 的他车。排队触发点上尚未放行的 MagCar 不计入占用(它们还在区外等候)。本车不计。
占用站点来源:车辆当前 siteID,以及 status.holdingLocks。任一命中列表即算 1 辆。
空位 = 本行容量 − 占用本行站点的车 − 与本行冲突的在途车
空位 ≥ 1 才对该车发启动。容量 1 表示:本线路内部(含冲突在途)最多一辆。
只比较同一管控区名称下的两行(或一行与一条在途记录)。不同区互不影响。
满足下面任一条件即冲突(互斥):
两组都不同、且站点列表不相交 → 不冲突,可同时放行。
| 场景 | 兼容组 | 内部站点 | 结果 |
|---|---|---|---|
| 旧表、未填兼容组 | 都空 | 任意 | 同区全部互斥 |
| 东西对向直行 | 都填 EW | 可不相交 | 同组,互斥(对向若也要并行,应拆成不同组且站点不相交) |
| 东西 / 南北互不交叉 | EW 与 NS | 10,11 与 20,21 | 不冲突,可并行 |
| 组名不同但抢同一段 | EW 与 NS | 都含 15 | 站点相交,仍互斥 |
| 左转与对向直行交叉 | 建议同组,或站点列出交叉段 | 有交集或同组 | 互斥 |
同一管控区内,先按下列比较函数排序,再贪心放行。不冲突的车排序先后不影响能否同时过,只影响扫描顺序。
当同区等待时长 W > 0,且两车优先级不同:
若 高优先级到达时刻 − 低优先级到达时刻 > W,则低优先级先走。
含义:低优先级更早到达,且已经比高优先级早到超过 W 秒,避免支路饿死。差值未超过 W 时,仍让优先级高的先走。
使用「>」而不是「≥」。例如 W=10,恰好早到 10 秒时仍按优先级。
排序后从前往后看。队头因本线已满或冲突在途没有空位时,跳过队头,继续检查后面的车。这样南北已占用时,队头若是南北,不会挡住后面可以走的东西向车辆。
重新加载配置会清空到达时刻和在途表,请避免在路口有车等待时频繁重载。
区名均为「十字路口A」。东西兼容组 EW,南北 NS。内部站点按方向拆开,容量均为 1。东西对向若现场确实会在同一段交汇,应把对向也拆站点或改为同组。
[
{ "TriggerSit": 8, "AreaName": "十字路口A", "CompatGroup": "EW", "Priority": 10, "WaitSeconds": 15, "ControlArea": "10,11", "ControlCapacity": 1, "IsUse": true },
{ "TriggerSit": 18, "AreaName": "十字路口A", "CompatGroup": "EW", "Priority": 10, "WaitSeconds": 15, "ControlArea": "12,13", "ControlCapacity": 1, "IsUse": true },
{ "TriggerSit": 9, "AreaName": "十字路口A", "CompatGroup": "NS", "Priority": 5, "WaitSeconds": 15, "ControlArea": "20,21", "ControlCapacity": 1, "IsUse": true },
{ "TriggerSit": 19, "AreaName": "十字路口A", "CompatGroup": "NS", "Priority": 5, "WaitSeconds": 15, "ControlArea": "22,23", "ControlCapacity": 1, "IsUse": true }
]
效果:东西一辆与南北一辆可同时过;同一兼容组内容量 1,同向或同组第二辆要等;南北优先级较低,但若已等待超过 15 秒且比干道更早到达,可以插队。
只配一行:触发点 8,区名为空,兼容组空,ControlArea 写内部点,容量 1。该点自成一区,他车占用内部点时不放行。
干道 Priority=10,支路 Priority=1,同区 WaitSeconds=20。支路先到、干道后到且时间差大于 20 秒时放支路;否则放干道。
| 机制 | 对象 | 关系 |
|---|---|---|
| 本进程 mag-control-areas.json | MagCar | 触发点停稳后发 StartMagCar |
| 地图 Fass2_ControlArea 等 | Mag2Car | StartStop=12 等待,放行改本车报文,本进程不介入 |
| TrafficControl 点锁 | MagCar / Mag2 路径执行 | 锁站点资源,与本表并行存在 |
| 交通管制 traffic.json | 区域互斥钩子 | 需单独启动「交通管制」进程 |
兼容组未区分,或内部站点写成同一串。请按方向拆兼容组并拆开 ControlArea。
把四个停车触发点写进了 ControlArea,容量又为 1,等待车被当成区内占用。触发点不要写入内部列表。
必须点「重新加载配置」或重启进程。路径必须是工作目录 Config/Signal,不是插件目录。
本策略不管 Mag2。Mag2 需在地图配置 Fass2_StartStop=12 及管控区字段。
当前实现小于 1 按 1 处理,不会变成不限流。
同组即互斥。对向要并行:不同组名,且内部站点不相交。
| 内容 | 位置 |
|---|---|
| 表字段 | StandardScene.Signal / MagControlAreaModel |
| 冲突、占用、容量 | MagControlAreaGate |
| 扫车、排队、在途、贪心放行 | MagControlRuntime.ScanAndRelease |
| 进程与重载 | MagTrafficMission |
| 迷毂列定义 | MiGu.Server / SignalDataStore(表 id: mag-control) |