using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace MultiWheelC.TrajectoryPlanning.PathSmoothing;
///
/// Local G2 路径平滑管线产生的不可变结果。
/// 只有可发布状态携带完整、已验证的路径和方向段;失败、取消和无效输入结果始终提供空集合,不能被当作部分路径消费。
///
public sealed class PathSmoothingResult
{
private static readonly IReadOnlyList EmptyPath =
new ReadOnlyCollection(new List());
private static readonly IReadOnlyList EmptySegments =
new ReadOnlyCollection(new List());
private static readonly IReadOnlyList EmptyRegionReports =
new ReadOnlyCollection(new List());
private PathSmoothingResult(
PathSmoothingStatus status,
SmoothingMethod? method,
IReadOnlyList path,
IReadOnlyList segments,
PathSmoothingDiagnostics diagnostics,
IReadOnlyList regionReports)
{
Status = status;
Method = method;
Path = path;
Segments = segments;
RegionReports = regionReports;
Diagnostics = diagnostics ?? new PathSmoothingDiagnostics(
new PathQualityMetrics(),
TimeSpan.Zero,
"No smoothing diagnostics were supplied.");
}
/// 本次平滑的终止状态;决定 和 是否可消费。
public PathSmoothingStatus Status { get; }
/// 成功发布路径时实际采用的平滑方法;失败结果为 。
public SmoothingMethod? Method { get; }
/// 成功时按起点到终点排列的不可变平滑路径;位置和弧长单位为 m,航向单位为 rad;失败时为空。
public IReadOnlyList Path { get; }
/// 成功时覆盖 的不可变方向段集合;失败时为空。
public IReadOnlyList Segments { get; }
/// 各 Local G2 区域的不可变处理报告;失败结果不包含区域发布记录。
public IReadOnlyList RegionReports { get; }
/// 质量指标、耗时和终止原因;始终存在,供调用方诊断成功或失败。
public PathSmoothingDiagnostics Diagnostics { get; }
/// 发布已经过独立几何、曲率、净空和连续碰撞复核的 Local G2 结果。
/// 可发布状态,只能是完整、部分改进、不需要平滑或保持原样之一。
/// 按起点到终点顺序排列的完整平滑路径;位置与弧长单位为 m,航向单位为 rad。
/// 覆盖完整路径的前进/倒车方向段集合。
/// 包含可行质量指标和终止说明的诊断快照。
/// 每个局部区域的不可变处理报告集合,不能为 。
/// 携带防御性复制路径、分段和区域报告的不可变可消费结果。
public static PathSmoothingResult PublishLocalG2(
PathSmoothingStatus status,
IReadOnlyList path,
IReadOnlyList segments,
PathSmoothingDiagnostics diagnostics,
IReadOnlyList regionReports)
{
if (status != PathSmoothingStatus.Complete &&
status != PathSmoothingStatus.PartialImprovement &&
status != PathSmoothingStatus.NotNeeded &&
status != PathSmoothingStatus.Unchanged)
{
throw new ArgumentException("Use a Local G2 publication status.", nameof(status));
}
if (regionReports == null)
throw new ArgumentNullException(nameof(regionReports));
ValidatePublishedResult(path, segments, diagnostics);
return new PathSmoothingResult(
status,
SmoothingMethod.LocalG2Quintic,
CopyReadOnly(path),
CopyReadOnly(segments),
diagnostics,
CopyReadOnly(regionReports));
}
/// 创建明确不发布路径的失败、取消或无效输入结果。
/// 非可发布的终止状态。
/// 失败原因、质量指标和耗时;为 时生成默认诊断。
/// 路径、方向段和区域报告均为空的不可变结果,不能作为部分路径使用。
public static PathSmoothingResult Failure(PathSmoothingStatus status, PathSmoothingDiagnostics diagnostics)
{
if (status == PathSmoothingStatus.Complete ||
status == PathSmoothingStatus.PartialImprovement ||
status == PathSmoothingStatus.NotNeeded ||
status == PathSmoothingStatus.Unchanged)
{
throw new ArgumentException("Use PublishLocalG2 to publish a path.", nameof(status));
}
if (!Enum.IsDefined(typeof(PathSmoothingStatus), status))
throw new ArgumentOutOfRangeException(nameof(status));
return new PathSmoothingResult(status, null, EmptyPath, EmptySegments, diagnostics, EmptyRegionReports);
}
private static void ValidatePublishedResult(
IReadOnlyList path,
IReadOnlyList segments,
PathSmoothingDiagnostics diagnostics)
{
if (path == null || path.Count == 0)
throw new ArgumentException("Published smoothing results require a non-empty path.", nameof(path));
if (segments == null || segments.Count == 0)
throw new ArgumentException("Published smoothing results require non-empty segments.", nameof(segments));
if (diagnostics == null || diagnostics.Metrics == null || !diagnostics.Metrics.IsFeasible)
throw new ArgumentException("Published smoothing results require feasible diagnostics.", nameof(diagnostics));
}
private static IReadOnlyList CopyReadOnly(IReadOnlyList source)
{
var copy = new List(source.Count);
for (int index = 0; index < source.Count; index++) copy.Add(source[index]);
return new ReadOnlyCollection(copy);
}
}