2.0协议完善加简单交管配置

This commit is contained in:
ykkokluo
2026-08-14 09:49:23 +08:00
parent a28bc68e23
commit 1e780c2b65
51 changed files with 4013 additions and 393 deletions
@@ -3,22 +3,23 @@ using SimpleCore.PropType;
using StandardScene.Magnetic.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
namespace StandardScene.Magnetic.Tasking
{
/// <summary>
/// 将站点路径与站点/边 fields 合并为 FASS 2.0 <c>0xB1</c> 节点序列。
/// 对齐 backend <c>CarRequestService.GetSendNodes</c> 的组包规则
/// 对齐 backend <c>CarRequestService.GetSendNodes</c>:边属性挂在节点<b>出边</b>上
/// </summary>
public static class Fass2TaskBuilder
{
public const byte StartStopPass = 1;
public const byte StartStopStop = 2;
public const byte StartStopControlStart = 11;
public const byte StartStopControlStop = 12;
public const byte StartStopPrecision = 22;
public static Fass2TaskPlan BuildPath(int startSiteId, int goalSiteId, Fass2TaskBuildOptions options,
Func<int, ushort> resolveNodeId)
Func<int, ushort> resolveNodeId, AbstractCar routingCar = null)
{
if (resolveNodeId == null)
{
@@ -26,7 +27,7 @@ namespace StandardScene.Magnetic.Tasking
}
options ??= new Fass2TaskBuildOptions();
var siteIds = Fass2PathFinder.GetSitesBetween(startSiteId, goalSiteId);
var siteIds = Fass2RouteHelper.GetSitesBetween(startSiteId, goalSiteId, routingCar);
if (siteIds.Count == 0)
{
throw new InvalidOperationException($"no path from site {startSiteId} to {goalSiteId}");
@@ -45,9 +46,17 @@ namespace StandardScene.Magnetic.Tasking
}
public static Fass2NodeMessage[] BuildSegment(int srcSiteId, int dstSiteId, Fass2TaskBuildOptions options,
Func<int, ushort> resolveNodeId)
Func<int, ushort> resolveNodeId, AbstractCar routingCar = null)
{
return BuildPath(srcSiteId, dstSiteId, options, resolveNodeId).Nodes.ToArray();
var plan = BuildPath(srcSiteId, dstSiteId, options, resolveNodeId, routingCar);
var nodes = plan.Nodes;
var array = new Fass2NodeMessage[nodes.Count];
for (var i = 0; i < nodes.Count; i++)
{
array[i] = nodes[i];
}
return array;
}
public static IReadOnlyList<Fass2NodeMessage[]> SplitBatches(IReadOnlyList<Fass2NodeMessage> nodes, int maxPerFrame = 10)
@@ -88,14 +97,15 @@ namespace StandardScene.Magnetic.Tasking
var site = SimpleLib.GetSite(siteId);
var siteAction = Fass2SiteFieldReader.Read(site);
var isLast = i == siteIds.Count - 1;
var prevSiteId = i > 0 ? siteIds[i - 1] : siteId;
var nextSiteId = isLast ? -1 : siteIds[i + 1];
Fass2TrackMotionData trackMotion = null;
Site prevSite = null;
if (i > 0)
Site currentSite = site;
Site nextSite = null;
if (!isLast)
{
prevSite = SimpleLib.GetSite(prevSiteId);
var track = FindTrack(prevSiteId, siteId);
nextSite = SimpleLib.GetSite(nextSiteId);
var track = Fass2RouteHelper.FindTrack(siteId, nextSiteId);
trackMotion = Fass2TrackFieldReader.Read(track);
}
@@ -103,9 +113,11 @@ namespace StandardScene.Magnetic.Tasking
{
Node = resolveNodeId(siteId),
StartStop = ResolveStartStop(siteAction, isLast),
Distance = i > 0 ? ComputeEdgeDistance(prevSite, site) : (ushort)0,
Speed = SpeedToProtocol(trackMotion?.Speed ?? options.DefaultSpeed, options.CarSpeed),
Orientation = ResolveOrientation(prevSite, site, trackMotion),
Distance = !isLast ? ComputeEdgeDistance(currentSite, nextSite) : (ushort)0,
Speed = !isLast
? SpeedToProtocol(trackMotion?.Speed ?? options.DefaultSpeed)
: (ushort)0,
Orientation = !isLast ? ResolveOrientation(currentSite, nextSite, trackMotion) : (byte)0,
Byroad = siteAction.Byroad ?? trackMotion?.Byroad ?? 0,
Direction = siteAction.Direction ?? trackMotion?.Direction ?? 0,
Lift = siteAction.Lift ?? 0,
@@ -185,42 +197,17 @@ namespace StandardScene.Magnetic.Tasking
return (ushort)Math.Min(ushort.MaxValue, Math.Max(1, Math.Round(length)));
}
private static ushort SpeedToProtocol(double trackSpeed, double carSpeed)
/// <summary>
/// 协议速度单位 0.1 m/min;地图 Speed 默认 m/min,≤1 视为旧版 m/s 兼容。
/// </summary>
public static ushort SpeedToProtocol(double speed)
{
var value = trackSpeed <= 0 ? carSpeed : trackSpeed;
var protocolSpeed = value <= 1
? (int)Math.Round(value * 600)
: (int)Math.Round(value * 10);
return (ushort)Math.Max(1, Math.Min(10000, protocolSpeed));
}
private static Track FindTrack(int fromSiteId, int toSiteId)
{
foreach (var track in SimpleLib.GetAllTracks())
if (speed > 0 && speed <= 1)
{
if (track.direction == 0)
{
if ((track.siteA == fromSiteId && track.siteB == toSiteId) ||
(track.siteB == fromSiteId && track.siteA == toSiteId))
{
return track;
}
continue;
}
if (track.direction == 1 && track.siteA == fromSiteId && track.siteB == toSiteId)
{
return track;
}
if (track.direction == 2 && track.siteB == fromSiteId && track.siteA == toSiteId)
{
return track;
}
speed *= 60;
}
return null;
return (ushort)Math.Max(1, Math.Min(10000, Math.Round(speed * 10)));
}
}
}