2.0协议完善加简单交管配置
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using SimpleCore;
|
||||
using SimpleCore.Library;
|
||||
using SimpleLite;
|
||||
using SimpleLite.Props;
|
||||
using SimpleLite.RCS;
|
||||
using SimpleLite.RCS.CarTypes;
|
||||
using StandardScene.CarTypes;
|
||||
using StandardScene.Chained;
|
||||
using StandardScene.Magnetic.Tasking;
|
||||
using StandardScene.Model;
|
||||
|
||||
namespace StandardScene
|
||||
{
|
||||
/// <summary>
|
||||
/// 磁导航 FASS 2.0 环线任务进程。
|
||||
/// <para>任务分配/触发/流量逻辑继承 Core <see cref="LoopMission"/>。</para>
|
||||
/// <para>导航执行由 <see cref="Mag2Car"/> 拦截 Loop 编译脚本(含 <c>Mag2Go</c> + <c>goalSite</c>),
|
||||
/// 改为单次全程 <c>0xB1</c> 状态机任务。</para>
|
||||
/// </summary>
|
||||
[MissionType(Name = "磁导航FASS2环线", editor = typeof(Mag2LoopMission))]
|
||||
public class Mag2LoopMission : LoopMission
|
||||
{
|
||||
[JsonIgnore] public override MissionStatus status { get; set; } = new LoopMissionStatus();
|
||||
|
||||
/// <summary>
|
||||
/// Mag2 空闲时可能尚未 TrafficReset(holdingLocks 为空),仍按上报站点/siteID 匹配在站车辆,
|
||||
/// 否则 AutoLoop 永远找不到车、加不上 goalSite。
|
||||
/// </summary>
|
||||
protected override Car FindCarArrivedAtSite(int siteId)
|
||||
{
|
||||
var byLock = base.FindCarArrivedAtSite(siteId);
|
||||
if (byLock != null)
|
||||
return byLock;
|
||||
|
||||
try
|
||||
{
|
||||
return SimpleLib.GetAllCars()
|
||||
.OfType<Mag2Car>()
|
||||
.FirstOrDefault(car =>
|
||||
{
|
||||
if (car?.tags == null || car.tags.Contains("occupied") || !car.tags.Contains("Online"))
|
||||
return false;
|
||||
if (car.status?.pendingLocks != null && car.status.pendingLocks.Length > 0)
|
||||
return false;
|
||||
if (car.status?.holdingLocks != null && car.status.holdingLocks.Length > 1)
|
||||
return false;
|
||||
|
||||
var physical = car.siteID > 0 ? car.siteID : car.GetLastSite();
|
||||
return physical == siteId;
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分配前尽量补上本站交管锁,保证 SelectCar/GoSite 的 GetLastSite 可用。
|
||||
/// </summary>
|
||||
protected override void AssignCarToTarget(Car car, int targetSiteId)
|
||||
{
|
||||
if (car is Mag2Car mag2)
|
||||
{
|
||||
EnsureMag2HoldingCurrentSite(mag2);
|
||||
}
|
||||
|
||||
base.AssignCarToTarget(car, targetSiteId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用当前占点匹配全部 LoopTask 展开路径(不过滤 IsViaPoint)。
|
||||
/// 路径用 BFS,避免 FindRoute 污染交管锁。
|
||||
/// </summary>
|
||||
public static List<Fass2ChainMatch> FindChainsContaining(int siteId)
|
||||
{
|
||||
var matches = new List<Fass2ChainMatch>();
|
||||
if (siteId <= 0)
|
||||
{
|
||||
return matches;
|
||||
}
|
||||
|
||||
IEnumerable<AbstractLoopMission> missions = null;
|
||||
try
|
||||
{
|
||||
missions = SimpleProject.proj?.Missions?.OfType<AbstractLoopMission>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
missions = null;
|
||||
}
|
||||
|
||||
if (missions == null)
|
||||
{
|
||||
return matches;
|
||||
}
|
||||
|
||||
foreach (var mission in missions)
|
||||
{
|
||||
IReadOnlyList<LoopTask> tasks;
|
||||
try
|
||||
{
|
||||
tasks = mission.GetTasks();
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tasks == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
var match = TryMatchTask(task, siteId);
|
||||
if (match != null)
|
||||
{
|
||||
matches.Add(match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public static bool TryResolveBelongingChain(
|
||||
int siteId,
|
||||
int? preferGoalSiteId,
|
||||
out Fass2ChainMatch selected,
|
||||
out string reason)
|
||||
{
|
||||
var matches = FindChainsContaining(siteId);
|
||||
return Fass2ReconnectChainSelector.TrySelect(matches, preferGoalSiteId, out selected, out reason);
|
||||
}
|
||||
|
||||
private static Fass2ChainMatch TryMatchTask(LoopTask task, int siteId)
|
||||
{
|
||||
if (task == null || task.CurrentStationId <= 0 || task.TargetStationId <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<int> fullPath;
|
||||
try
|
||||
{
|
||||
fullPath = Fass2RouteHelper.GetSitesBetween(task.CurrentStationId, task.TargetStationId, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (fullPath == null || fullPath.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var index = fullPath.IndexOf(siteId);
|
||||
if (index < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var remaining = fullPath.Skip(index).ToList();
|
||||
return new Fass2ChainMatch
|
||||
{
|
||||
TaskId = task.Id,
|
||||
TaskPriority = task.Priority,
|
||||
CurrentSiteId = siteId,
|
||||
TargetSiteId = task.TargetStationId,
|
||||
IndexInPath = index,
|
||||
DistanceToTarget = Math.Max(0, fullPath.Count - index - 1),
|
||||
IsAtStartPoint = index == 0,
|
||||
IsAtEndPoint = index == fullPath.Count - 1,
|
||||
FullPath = fullPath,
|
||||
RemainingPath = remaining
|
||||
};
|
||||
}
|
||||
|
||||
private static void EnsureMag2HoldingCurrentSite(Mag2Car car)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (car.status?.holdingLocks != null && car.status.holdingLocks.Length == 1)
|
||||
return;
|
||||
|
||||
var siteId = car.siteID > 0 ? car.siteID : car.GetLastSite();
|
||||
if (siteId <= 0)
|
||||
return;
|
||||
|
||||
var site = SimpleLib.GetSite(siteId);
|
||||
if (site == null)
|
||||
return;
|
||||
|
||||
car.TrafficReset(site, true, strict: false);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 交管失败时仍允许打上 goalSite,后续 GoSite/状态机会再处理
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using SimpleLite.Props;
|
||||
using SimpleLite.RCS;
|
||||
using StandardScene.Chained;
|
||||
|
||||
namespace StandardScene
|
||||
{
|
||||
/// <summary>
|
||||
/// 磁导航 FASS 2.0 环线任务进程。
|
||||
/// <para>任务分配/触发/流量逻辑完全继承 Core <see cref="LoopMission"/>,不修改 Core。</para>
|
||||
/// <para>导航执行由 <see cref="MagFass2Car"/> 拦截 Loop 编译脚本(含 <c>MagFass2Go</c> + <c>goalSite</c>),
|
||||
/// 改为单次全程 <c>0xB1</c> 状态机任务。</para>
|
||||
/// <para>场景内可继续使用原 <see cref="LoopMission"/>;本类型仅作磁导航 FASS2 场景标识。</para>
|
||||
/// </summary>
|
||||
[MissionType(Name = "磁导航FASS2环线", editor = typeof(MagFass2LoopMission))]
|
||||
public class MagFass2LoopMission : LoopMission
|
||||
{
|
||||
[JsonIgnore] public override MissionStatus status { get; set; } = new LoopMissionStatus();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user