using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace MultiWheelC.TrajectoryPlanning.PathSmoothing;
/// 路径平滑的最终不可变结果。
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,
0,
0d,
"No smoothing diagnostics were supplied.");
}
/// 最终发布状态。
public PathSmoothingStatus Status { get; }
/// 成功或回退时的实际(或尝试)平滑方法;失败时为空。
public SmoothingMethod? Method { get; }
/// 成功或经过复核的回退路径;其他状态始终为空且不可变。
public IReadOnlyList Path { get; }
/// 覆盖 的方向分段;其他状态始终为空且不可变。
public IReadOnlyList Segments { get; }
/// 局部 G2 各检测区域的不可变报告;传统算法结果为空。
public IReadOnlyList RegionReports { get; }
/// 本次平滑的质量和终止诊断;始终非空。
public PathSmoothingDiagnostics Diagnostics { get; }
/// 创建已通过所有复核的平滑结果。
public static PathSmoothingResult Success(
SmoothingMethod method,
IReadOnlyList path,
IReadOnlyList segments,
PathSmoothingDiagnostics diagnostics)
{
ValidatePublishedResult(method, path, segments, diagnostics);
return new PathSmoothingResult(
PathSmoothingStatus.Success,
method,
CopyReadOnly(path),
CopyReadOnly(segments),
diagnostics,
EmptyRegionReports);
}
/// 创建经过完整复核的原始粗路径回退结果。
public static PathSmoothingResult Fallback(
SmoothingMethod attemptedMethod,
IReadOnlyList path,
IReadOnlyList segments,
PathSmoothingDiagnostics diagnostics)
{
ValidatePublishedResult(attemptedMethod, path, segments, diagnostics);
return new PathSmoothingResult(
PathSmoothingStatus.FallbackToCoarsePath,
attemptedMethod,
CopyReadOnly(path),
CopyReadOnly(segments),
diagnostics,
EmptyRegionReports);
}
/// 发布经过完整复核的局部 G2 预平滑结果。
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(SmoothingMethod.LocalG2Quintic, 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.Success ||
status == PathSmoothingStatus.FallbackToCoarsePath ||
status == PathSmoothingStatus.Complete ||
status == PathSmoothingStatus.PartialImprovement ||
status == PathSmoothingStatus.NotNeeded ||
status == PathSmoothingStatus.Unchanged)
throw new ArgumentException("Use Success or Fallback 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(
SmoothingMethod method,
IReadOnlyList path,
IReadOnlyList segments,
PathSmoothingDiagnostics diagnostics)
{
if (!Enum.IsDefined(typeof(SmoothingMethod), method))
throw new ArgumentOutOfRangeException(nameof(method));
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);
}
}