IAgvPathService.cs 5.91 KB
using Rcs.Application.Services.PathFind.Models;

namespace Rcs.Application.Services.PathFind;

/// <summary>
/// AGV寻路服务接口(统一锁模式)
/// @author zzy
/// </summary>
public interface IAgvPathService
{
    /// <summary>
    /// 计算路径
    /// </summary>
    Task<PathResult> CalculatePathAsync(PathRequest request, CancellationToken ct = default);

    /// <summary>
    /// 重新规划路径(障碍物/死锁/任务变更触发)
    /// </summary>
    /// <param name="request">路径请求</param>
    /// <param name="mapCode">地图编码(用于释放统一锁)</param>
    /// <param name="reason">重规划原因</param>
    /// <param name="ct">取消令牌</param>
    Task<PathResult> ReplanPathAsync(PathRequest request, string mapCode, string reason, CancellationToken ct = default);

    /// <summary>
    /// 锁定路径段(跨地图统一锁模式)
    /// 使用 MapCode:NodeCode/EdgeCode 作为Key进行跨厂家地图的统一锁管理
    /// </summary>
    /// <param name="robotId">机器人ID</param>
    /// <param name="mapCode">地图编码(同一物理环境的所有厂家地图使用相同的MapCode)</param>
    /// <param name="segments">路径段列表(需包含NodeCode和EdgeCode)</param>
    /// <param name="lockTimeMs">锁定时间(毫秒)</param>
    /// <returns>锁定结果</returns>
    Task<LockRequestResult> LockPathSegmentsAsync(Guid robotId, string mapCode, List<PathSegmentWithCode> segments, int lockTimeMs = 10000);

    /// <summary>
    /// 释放路径段(跨地图统一锁模式)
    /// </summary>
    /// <param name="robotId">机器人ID</param>
    /// <param name="mapCode">地图编码</param>
    /// <param name="segments">路径段列表</param>
    /// <returns>释放的锁数量</returns>
    Task<int> ReleasePathSegmentsAsync(string mapCode,
            IEnumerable<string> nodeCodes,
            IEnumerable<string> edgeCodes,
            Guid robotId);

    /// <summary>
    /// 释放机器人的所有锁(可选保留当前位置节点相关锁)
    /// </summary>
    /// <param name="robotId">机器人ID</param>
    /// <param name="currentMapCode">当前位置地图编码(可选)</param>
    /// <param name="currentNodeCode">当前位置节点编码(可选)</param>
    /// <returns>释放的锁数量</returns>
    Task<int> ReleaseAllLocksAsync(Guid robotId, string? currentMapCode = null, string? currentNodeCode = null);
    /// <summary>
    /// 续期机器人的所有锁
    /// </summary>
    /// <param name="robotId">机器人ID</param>
    /// <param name="ttlSeconds">续期时长(秒)</param>
    /// <returns>续期的锁数量</returns>
    Task<int> RenewAllLocksAsync(Guid robotId, int ttlSeconds = 30);

    /// <summary>
    /// 尝试锁定下一段路径并判断是否存在逆向占用
    /// </summary>
    /// <param name="mapCode">地图编码</param>
    /// <param name="segments">路径段列表(包含节点和边编码)</param>
    /// <param name="robotId">机器人ID</param>
    /// <param name="ttlSeconds">锁过期时间(秒)</param>
    /// <returns>下一段路径锁定结果</returns>
    Task<NextSegmentLockResult> TryAcquireNextSegmentLockAsync(
        string mapCode,
        IEnumerable<PathSegmentWithCode> segments,
        Guid robotId,
        int ttlSeconds = 30);

    /// <summary>
    /// 严格 binding 加锁前冲突预检。
    /// </summary>
    Task<BindingLockPreCheckResult> ValidateBindingConflictsBeforeLockAsync(
        string mapCode,
        Guid robotId,
        IEnumerable<BindingLockRequest> bindings);

    Task<SweptConflictCheckResult> CheckSweptGeometryConflictAsync(SweptConflictCheckRequest request);

    Task RegisterPlannedSweepAsync(SweptConflictCheckRequest request, int ttlSeconds = 30);

    Task ReleasePlannedSweepAsync(string mapCode, Guid robotId, string bindingId);

    Task RenewPlannedSweepAsync(string mapCode, Guid robotId, string bindingId, int ttlSeconds = 30);

    /// <summary>
    /// 按严格 binding 模型加锁。
    /// </summary>
    Task<BindingLockRequestResult> TryAcquireBindingsAsync(
        string mapCode,
        Guid robotId,
        IEnumerable<BindingLockRequest> bindings,
        int ttlSeconds = 30);

    /// <summary>
    /// 按 bindingId 精确释放锁引用。
    /// </summary>
    Task<int> ReleaseBindingsAsync(
        string mapCode,
        Guid robotId,
        IEnumerable<string> bindingIds);

    /// <summary>
    /// 回滚一批已加成功的 binding。
    /// </summary>
    Task<int> RollbackBindingsAsync(
        string mapCode,
        Guid robotId,
        IEnumerable<string> bindingIds);

    /// <summary>
    /// 检测路径冲突(跨地图)
    /// </summary>
    Task<PathConflictResult> CheckPathConflictAsync(Guid robotId, string mapCode, List<PathSegmentWithCode> segments);

    /// <summary>
    /// 使指定地图的图缓存失效
    /// </summary>
    void InvalidateGraphCache(Guid mapId);

    /// <summary>
    /// 清空所有图缓存
    /// </summary>
    void ClearAllGraphCache();

    /// <summary>
    /// 更新机器人状态
    /// </summary>
    void UpdateRobotState(RobotRuntimeState state);

    /// <summary>
    /// 获取或构建寻路图
    /// @author zzy
    /// </summary>
    Task<PathGraph?> GetOrBuildGraphAsync(Guid mapId);

    /// <summary>
    /// 热构建指定地图(重新加载地图数据并重建图缓存)
    /// @author zzy
    /// </summary>
    /// <param name="mapId">地图ID</param>
    /// <returns>重建后的寻路图</returns>
    Task<PathGraph?> HotBuildGraphAsync(Guid mapId);

    /// <summary>
    /// 构建全局路径上下文
    /// @author zzy
    /// </summary>
    GlobalPathContext BuildGlobalPathContext(Guid excludeRobotId);

    /// <summary>
    /// 使用地图图结构补全路径段的NodeCode信息
    /// @author zzy
    /// </summary>
    List<PathSegmentWithCode> EnrichSegmentsWithCode(List<PathSegment> segments, PathGraph graph);
}