using System.Collections.Generic; using System.Collections.ObjectModel; using MultiWheelC.TrajectoryPlanning.CoarsePath; using MultiWheelC.TrajectoryPlanning.Mapping; namespace MultiWheelC.TrajectoryPlanning.PathSmoothing; /// /// 一次路径平滑所需的不可变输入快照。 /// 粗路径、方向段、车辆和配置均在构造时复制;地图保留为调用方已冻结的 快照。 /// public sealed class PathSmoothingRequest { private readonly VehicleParameters _vehicle; private readonly PathSmoothingConfiguration _configuration; /// /// 创建路径平滑请求,并防御性复制可变的路径、分段、车辆和配置输入。 /// /// 按起点到终点顺序排列的粗路径点集合;位置与弧长单位为 m,航向单位为 rad。 /// 对应的前进/倒车包含式方向分段集合。 /// 用于完整车体碰撞与净空复核的已准备不可变规划地图快照。 /// 车辆长宽、安全余量和曲率约束;长度单位为 m,曲率单位为 1/m。 /// 本次平滑的采样、净空、曲率和 Local G2 配置;构造后不会与调用方共享可变实例。 public PathSmoothingRequest( IReadOnlyList coarsePath, IReadOnlyList segments, PlanningGridMap map, VehicleParameters vehicle, PathSmoothingConfiguration configuration) { CoarsePath = CopyReadOnly(coarsePath); Segments = CopyReadOnly(segments); Map = map; _vehicle = CopyVehicle(vehicle); _configuration = CopyConfiguration(configuration); } /// 原始粗路径的只读快照,按起点到终点顺序排列;位置与弧长单位为 m,航向单位为 rad。 public IReadOnlyList CoarsePath { get; } /// 原始粗路径方向分段的只读快照;每段标识连续前进或倒车区间。 public IReadOnlyList Segments { get; } /// 用于平滑后完整车体碰撞和净空复核的已冻结规划栅格地图快照。 public PlanningGridMap Map { get; } /// 车辆几何与最大曲率约束的不可变快照副本。 public VehicleParameters Vehicle => CopyVehicle(_vehicle); /// 本次平滑配置的不可变快照副本。 public PathSmoothingConfiguration Configuration => CopyConfiguration(_configuration); private static IReadOnlyList CopyReadOnly(IReadOnlyList source) { var copy = new List(source == null ? 0 : source.Count); if (source != null) { for (int index = 0; index < source.Count; index++) copy.Add(source[index]); } return new ReadOnlyCollection(copy); } private static VehicleParameters CopyVehicle(VehicleParameters source) { if (source == null) return null; return new VehicleParameters { LengthMeters = source.LengthMeters, WidthMeters = source.WidthMeters, SafetyMarginMeters = source.SafetyMarginMeters, MaximumCurvaturePerMeter = source.MaximumCurvaturePerMeter, MinimumTurningRadiusMeters = source.MinimumTurningRadiusMeters, }; } private static PathSmoothingConfiguration CopyConfiguration(PathSmoothingConfiguration source) { if (source == null) return null; var copy = new PathSmoothingConfiguration { OutputSpacingMeters = source.OutputSpacingMeters, MaximumCollisionCheckStepMeters = source.MaximumCollisionCheckStepMeters, MinimumClearanceReserveMeters = source.MinimumClearanceReserveMeters, CurvatureLimitRadiusToleranceMeters = source.CurvatureLimitRadiusToleranceMeters, }; copy.LocalG2Quintic.MinimumWindowLengthMeters = source.LocalG2Quintic.MinimumWindowLengthMeters; copy.LocalG2Quintic.PreferredWindowLengthMeters = source.LocalG2Quintic.PreferredWindowLengthMeters; copy.LocalG2Quintic.MaximumWindowLengthMeters = source.LocalG2Quintic.MaximumWindowLengthMeters; copy.LocalG2Quintic.MaximumDeviationMeters = source.LocalG2Quintic.MaximumDeviationMeters; copy.LocalG2Quintic.AbsoluteCurvatureJumpFloorPerMeter = source.LocalG2Quintic.AbsoluteCurvatureJumpFloorPerMeter; copy.LocalG2Quintic.CurvatureJumpRatioOfMaximum = source.LocalG2Quintic.CurvatureJumpRatioOfMaximum; copy.LocalG2Quintic.MinimumPeakGradientImprovementRatio = source.LocalG2Quintic.MinimumPeakGradientImprovementRatio; copy.LocalG2Quintic.MaximumVariationCostRegressionRatio = source.LocalG2Quintic.MaximumVariationCostRegressionRatio; copy.LocalG2Quintic.MaximumCandidatesPerRegion = source.LocalG2Quintic.MaximumCandidatesPerRegion; return copy; } }