GlobalNavigationContracts.cs 11.2 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Rcs.Application.Services.PathFind.Models;

namespace Rcs.Application.Services.PathFind.Realtime;

/// <summary>
/// 全局导航协调器返回的路径调整动作。
/// </summary>
public enum RouteAdjustmentAction
{
    /// <summary>
    /// 继续按当前路径发送。
    /// </summary>
    Continue = 0,

    /// <summary>
    /// 暂停发送并进入等待窗口。
    /// </summary>
    Hold = 1,

    /// <summary>
    /// 对未发送尾段应用补丁路径。
    /// </summary>
    PatchTail = 2,

    /// <summary>
    /// 触发尾段重规划并替换。
    /// </summary>
    ReplanTail = 3
}

/// <summary>
/// 全局导航决策共享的策略编码。
/// </summary>
public static class AvoidanceStrategyCodes
{
    /// <summary>
    /// 无需调整,直接继续。
    /// </summary>
    public const string Continue = "Continue";

    /// <summary>
    /// 就近等待。
    /// </summary>
    public const string WaitNearest = "WaitNearest";

    /// <summary>
    /// 路口占位排队。
    /// </summary>
    public const string JunctionOccupy = "JunctionOccupy";

    /// <summary>
    /// 局部绕行。
    /// </summary>
    public const string LocalDetour = "LocalDetour";

    /// <summary>
    /// 侧向让行。
    /// </summary>
    public const string LateralYield = "LateralYield";

    /// <summary>
    /// 泊车让行。
    /// </summary>
    public const string ParkingYield = "ParkingYield";

    /// <summary>
    /// 退让回撤。
    /// </summary>
    public const string Retreat = "Retreat";

    /// <summary>
    /// 尾段重规划。
    /// </summary>
    public const string ReplanTail = "ReplanTail";
}

/// <summary>
/// 全局导航状态机共享的路线模式编码。
/// </summary>
public static class RouteModeCodes
{
    /// <summary>
    /// 正常发送模式。
    /// </summary>
    public const string Normal = "Normal";

    /// <summary>
    /// 在等待节点保持等待。
    /// </summary>
    public const string HoldingAtWaitNode = "HoldingAtWaitNode";

    /// <summary>
    /// 路口排队等待。
    /// </summary>
    public const string QueueingForJunction = "QueueingForJunction";

    /// <summary>
    /// 占用路口等待放行。
    /// </summary>
    public const string OccupyingJunction = "OccupyingJunction";

    /// <summary>
    /// 绕行执行中。
    /// </summary>
    public const string Detouring = "Detouring";

    /// <summary>
    /// 回归主路径中。
    /// </summary>
    public const string Rejoining = "Rejoining";

    /// <summary>
    /// 等待重规划结果。
    /// </summary>
    public const string ReplanPending = "ReplanPending";

    /// <summary>
    /// 阻塞保护态。
    /// </summary>
    public const string Blocked = "Blocked";
}

/// <summary>
/// 机器人处于等待升级阶段时,策略选择器使用的输入参数。
/// </summary>
public sealed class AvoidanceSelectionContext
{
    /// <summary>
    /// 连续冲突失败次数。
    /// </summary>
    public int FailStreak { get; set; }

    /// <summary>
    /// 是否存在逆向冲突。
    /// </summary>
    public bool HasReverseConflict { get; set; }

    /// <summary>
    /// 触发等待策略的阈值。
    /// </summary>
    public int EscalateWaitThreshold { get; set; }

    /// <summary>
    /// 触发绕行策略的阈值。
    /// </summary>
    public int EscalateDetourThreshold { get; set; }

    /// <summary>
    /// 触发侧向让行策略的阈值。
    /// </summary>
    public int EscalateLateralYieldThreshold { get; set; }

    /// <summary>
    /// 触发泊车让行策略的阈值。
    /// </summary>
    public int EscalateParkingThreshold { get; set; }

    /// <summary>
    /// 触发退让策略的阈值。
    /// </summary>
    public int EscalateRetreatThreshold { get; set; }

    /// <summary>
    /// 触发重规划策略的阈值。
    /// </summary>
    public int EscalateReplanThreshold { get; set; }

    /// <summary>
    /// 是否启用侧向让行。
    /// </summary>
    public bool EnableLateralYield { get; set; }

    /// <summary>
    /// 是否启用泊车让行。
    /// </summary>
    public bool EnableParkingYield { get; set; }

    /// <summary>
    /// 是否启用退让。
    /// </summary>
    public bool EnableRetreat { get; set; }
}

/// <summary>
/// 根据运行时上下文选择候选避让策略。
/// </summary>
public interface IAvoidanceStrategySelector
{
    /// <summary>
    /// 按当前上下文选择候选策略编码列表。
    /// </summary>
    IReadOnlyList<string> SelectHoldCandidates(AvoidanceSelectionContext context);
}

/// <summary>
/// 用于替换未发送路径的尾段补丁载荷。
/// </summary>
public sealed class TailPatch
{
    /// <summary>
    /// 补丁唯一标识。
    /// </summary>
    public Guid PatchId { get; set; } = Guid.NewGuid();

    /// <summary>
    /// 应用补丁所期望的路径版本号。
    /// </summary>
    public long ExpectedPlanVersion { get; set; }

    /// <summary>
    /// 补丁起始路口索引。
    /// </summary>
    public int FromJunctionIndex { get; set; }

    /// <summary>
    /// 补丁起始资源段索引。
    /// </summary>
    public int FromResourceIndex { get; set; }

    /// <summary>
    /// 触发补丁的策略编码。
    /// </summary>
    public string StrategyCode { get; set; } = string.Empty;

    /// <summary>
    /// 补丁原因说明。
    /// </summary>
    public string Reason { get; set; } = string.Empty;

    /// <summary>
    /// 建议等待节点编码。
    /// </summary>
    public string? WaitNodeCode { get; set; }

    /// <summary>
    /// 期望回归节点编码。
    /// </summary>
    public string? RejoinNodeCode { get; set; }

    /// <summary>
    /// 新尾段路径(三层结构:路口段/资源段/原子段)。
    /// </summary>
    public List<List<List<PathSegmentWithCode>>> NewTail { get; set; } = new();
}

/// <summary>
/// 全局导航协调器生成的决策结果。
/// </summary>
public sealed class RouteAdjustmentDecision
{
    /// <summary>
    /// 调整动作类型。
    /// </summary>
    public RouteAdjustmentAction Action { get; set; } = RouteAdjustmentAction.Continue;

    /// <summary>
    /// 决策说明消息。
    /// </summary>
    public string Message { get; set; } = string.Empty;

    /// <summary>
    /// 决策对应策略编码。
    /// </summary>
    public string StrategyCode { get; set; } = "Continue";

    /// <summary>
    /// 建议等待截止时间(UTC)。
    /// </summary>
    public DateTime? SuggestedHoldUntilUtc { get; set; }

    /// <summary>
    /// 待应用的尾段补丁(可空)。
    /// </summary>
    public TailPatch? Patch { get; set; }
}

/// <summary>
/// 全局导航协调器消费的实时状态事件。
/// </summary>
public sealed class RobotStateNavigationEvent
{
    /// <summary>
    /// 机器人ID。
    /// </summary>
    public Guid RobotId { get; set; }

    /// <summary>
    /// 机器人制造商编码。
    /// </summary>
    public string RobotManufacturer { get; set; } = string.Empty;

    /// <summary>
    /// 机器人序列号。
    /// </summary>
    public string RobotSerialNumber { get; set; } = string.Empty;

    /// <summary>
    /// 最后经过节点编码。
    /// </summary>
    public string? LastNodeCode { get; set; }

    /// <summary>
    /// 是否处于行驶中。
    /// </summary>
    public bool IsDriving { get; set; }

    /// <summary>
    /// 事件发生时间(UTC)。
    /// </summary>
    public DateTime OccurredAtUtc { get; set; } = DateTime.Now;
}

/// <summary>
/// 协调器消费的锁冲突事件(加锁失败/逆向冲突)。
/// </summary>
public sealed class LockConflictNavigationEvent
{
    /// <summary>
    /// 机器人ID。
    /// </summary>
    public Guid RobotId { get; set; }

    /// <summary>
    /// 地图编码。
    /// </summary>
    public string MapCode { get; set; } = string.Empty;

    /// <summary>
    /// 冲突节点编码。
    /// </summary>
    public string? NodeCode { get; set; }

    /// <summary>
    /// 冲突边编码。
    /// </summary>
    public string? EdgeCode { get; set; }

    /// <summary>
    /// 是否为逆向冲突。
    /// </summary>
    public bool HasReverseConflict { get; set; }

    /// <summary>
    /// 冲突失败原因。
    /// </summary>
    public string? FailureReason { get; set; }

    /// <summary>
    /// 事件发生时间(UTC)。
    /// </summary>
    public DateTime OccurredAtUtc { get; set; } = DateTime.Now;
}

/// <summary>
/// 状态事件驱动的全局导航协调器。
/// </summary>
public interface IGlobalNavigationCoordinator
{
    /// <summary>
    /// 发布机器人实时状态事件。
    /// </summary>
    Task PublishStateEventAsync(RobotStateNavigationEvent evt, CancellationToken ct = default);

    /// <summary>
    /// 发布锁冲突事件(加锁检查失败或逆向冲突)。
    /// </summary>
    Task PublishLockConflictEventAsync(LockConflictNavigationEvent evt, CancellationToken ct = default);

    /// <summary>
    /// 应用发送前路径调整决策。
    /// </summary>
    Task<RouteAdjustmentDecision> TryAdjustBeforeSendAsync(
        Guid robotId,
        VdaSegmentedPathCache cache,
        string? lastNodeCode,
        bool isDriving,
        CancellationToken ct = default);
}

/// <summary>
/// 将尾段补丁应用到 VDA 分段缓存。
/// </summary>
public interface ITailPatchApplier
{
    /// <summary>
    /// 将尾段补丁应用到缓存,失败时返回失败原因。
    /// </summary>
    bool TryApplyPatch(VdaSegmentedPathCache cache, TailPatch patch, out string failureReason);
}

/// <summary>
/// 等待/排队恢复触发请求。
/// </summary>
public sealed class HoldResumeRequest
{
    /// <summary>
    /// 机器人ID。
    /// </summary>
    public Guid RobotId { get; set; }

    /// <summary>
    /// 机器人制造商编码。
    /// </summary>
    public string RobotManufacturer { get; set; } = string.Empty;

    /// <summary>
    /// 机器人序列号。
    /// </summary>
    public string RobotSerialNumber { get; set; } = string.Empty;

    /// <summary>
    /// 任务ID。
    /// </summary>
    public Guid TaskId { get; set; }

    /// <summary>
    /// 子任务ID。
    /// </summary>
    public Guid SubTaskId { get; set; }

    /// <summary>
    /// 路径缓存Key。
    /// </summary>
    public string PathCacheKey { get; set; } = string.Empty;

    /// <summary>
    /// 恢复时要求匹配的路径版本号。
    /// </summary>
    public long ExpectedPlanVersion { get; set; }

    /// <summary>
    /// 期望保持的等待节点编码。
    /// </summary>
    public string? HoldNodeCode { get; set; }

    /// <summary>
    /// 计划恢复调度时间(UTC)。
    /// </summary>
    public DateTime ResumeAtUtc { get; set; } = DateTime.Now;
}

/// <summary>
/// 为等待/排队状态调度延迟恢复尝试。
/// </summary>
public interface IGlobalNavigationResumeScheduler
{
    /// <summary>
    /// 提交一次延迟恢复调度请求。
    /// </summary>
    Task ScheduleResumeAsync(HoldResumeRequest request, CancellationToken ct = default);
}