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); } }