68 lines
3.4 KiB
C#
68 lines
3.4 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Collections.ObjectModel;
|
||
|
||
namespace MultiWheelC.TrajectoryPlanning.CoarsePath;
|
||
|
||
/// <summary>
|
||
/// 一次粗路径规划的最终不可变结果。
|
||
/// 只有 <see cref="Status"/> 为 <see cref="PlanningStatus.Success"/> 时才携带非空路径与方向分段;其他状态始终返回空只读集合。
|
||
/// </summary>
|
||
public sealed class PlanningResult
|
||
{
|
||
private static readonly IReadOnlyList<CoarsePathPoint> EmptyPath = new ReadOnlyCollection<CoarsePathPoint>(new List<CoarsePathPoint>());
|
||
private static readonly IReadOnlyList<PathSegment> EmptySegments = new ReadOnlyCollection<PathSegment>(new List<PathSegment>());
|
||
|
||
private PlanningResult(PlanningStatus status, PlanningDiagnostics diagnostics, IReadOnlyList<CoarsePathPoint> path, IReadOnlyList<PathSegment> segments)
|
||
{
|
||
Status = status;
|
||
Diagnostics = diagnostics ?? new PlanningDiagnostics(terminationReason: "未提供诊断信息。");
|
||
Path = path;
|
||
Segments = segments;
|
||
}
|
||
|
||
/// <summary>规划最终状态;只有 <see cref="PlanningStatus.Success"/> 可以发布路径。</summary>
|
||
public PlanningStatus Status { get; }
|
||
|
||
/// <summary>节点、耗时、路径长度、净空和终止原因统计;始终非空。</summary>
|
||
public PlanningDiagnostics Diagnostics { get; }
|
||
|
||
/// <summary>成功时的稠密粗路径;失败时为不可修改的空集合。</summary>
|
||
public IReadOnlyList<CoarsePathPoint> Path { get; }
|
||
|
||
/// <summary>成功时覆盖 <see cref="Path"/> 的包含式方向分段;失败时为不可修改的空集合。</summary>
|
||
public IReadOnlyList<PathSegment> Segments { get; }
|
||
|
||
/// <summary>
|
||
/// 创建成功结果。
|
||
/// 参数:path 与 segments 必须均为非空;diagnostics 为本次规划的统计快照。参数不符合要求时抛出 <see cref="ArgumentException"/>,防止以成功状态发布不完整路径。
|
||
/// </summary>
|
||
public static PlanningResult Success(IReadOnlyList<CoarsePathPoint> path, IReadOnlyList<PathSegment> segments, PlanningDiagnostics diagnostics)
|
||
{
|
||
if (path == null || path.Count == 0)
|
||
throw new ArgumentException("Successful planning results require a non-empty path.", nameof(path));
|
||
if (segments == null || segments.Count == 0)
|
||
throw new ArgumentException("Successful planning results require non-empty segments.", nameof(segments));
|
||
return new PlanningResult(PlanningStatus.Success, diagnostics, CopyReadOnly(path), CopyReadOnly(segments));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建失败、取消或资源受限结果。
|
||
/// 参数:status 不能为 <see cref="PlanningStatus.Success"/>;diagnostics 会原样保留。返回结果的路径与分段始终为空只读集合。
|
||
/// </summary>
|
||
public static PlanningResult Failure(PlanningStatus status, PlanningDiagnostics diagnostics)
|
||
{
|
||
if (status == PlanningStatus.Success)
|
||
throw new ArgumentException("Use Success to create a successful planning result.", nameof(status));
|
||
return new PlanningResult(status, diagnostics, EmptyPath, EmptySegments);
|
||
}
|
||
|
||
private static IReadOnlyList<T> CopyReadOnly<T>(IReadOnlyList<T> source)
|
||
{
|
||
var copy = new List<T>(source.Count);
|
||
for (int index = 0; index < source.Count; index++)
|
||
copy.Add(source[index]);
|
||
return new ReadOnlyCollection<T>(copy);
|
||
}
|
||
}
|