using System; using System.Collections.Generic; using System.Threading; using MultiWheelC.TrajectoryPlanning.CoarsePath; using MultiWheelC.TrajectoryPlanning.CoarsePath.Facade; using MultiWheelC.TrajectoryPlanning.PathSmoothing.Output.Comparison; namespace MultiWheelC.TrajectoryPlanning.PathSmoothing.Test; /// 将快速夹具或现有粗路径业务结果转换为独立平滑比较请求。 public static class SmoothingScenarioFactory { /// 不运行 Hybrid A*,从已验证的 JSON 夹具创建八个快速比较请求。 public static IReadOnlyList CreateFixtureRequests(string fixturePath) { IReadOnlyList fixtures = SmoothingScenarioFixtureLoader.LoadAndVerify(fixturePath); var requests = new List(fixtures.Count); for (int index = 0; index < fixtures.Count; index++) { SmoothingScenarioFixture fixture = fixtures[index]; requests.Add(new PathSmoothingComparisonRequest( new PathSmoothingRequest( fixture.Path, fixture.Segments, SmoothingScenarioFixtureLoader.BuildMap(fixture), SmoothingScenarioFixtureLoader.BuildVehicle(fixture), new PathSmoothingConfiguration()))); } return requests.AsReadOnly(); } /// 把现有 已规划成功的结果转换为比较请求。 public static PathSmoothingComparisonRequest CreateEndToEndRequest( CoarsePathPlanningJob job, CoarsePathPlanningJobResult result) { if (job == null || result == null || result.MapResult == null || result.MapResult.Map == null || result.PlanningResult == null || result.PlanningResult.Status != PlanningStatus.Success) throw new ArgumentException("只能从包含成功地图和粗路径的业务结果创建平滑比较请求。", nameof(result)); return new PathSmoothingComparisonRequest(new PathSmoothingRequest( CopyWithFiniteClearance(result.PlanningResult.Path, result.MapResult.Map), result.PlanningResult.Segments, result.MapResult.Map, job.Vehicle, new PathSmoothingConfiguration())); } internal static IReadOnlyList CopyWithFiniteClearance( IReadOnlyList source, MultiWheelC.TrajectoryPlanning.Mapping.PlanningGridMap map) { double widthMeters = (map.Bounds.XMax - map.Bounds.XMin) / 1000d; double heightMeters = (map.Bounds.YMax - map.Bounds.YMin) / 1000d; double finiteEmptyMapClearance = Math.Sqrt(widthMeters * widthMeters + heightMeters * heightMeters); var copy = new List(source.Count); for (int index = 0; index < source.Count; index++) { CoarsePathPoint point = source[index]; double clearance = double.IsPositiveInfinity(point.BodyClearance) ? finiteEmptyMapClearance : point.BodyClearance; copy.Add(new CoarsePathPoint( point.X, point.Y, point.Heading, point.UnwrappedHeading, point.ArcLength, point.Direction, point.VehicleCurvature, clearance, point.IsGearSwitchPoint, point.Source)); } return copy.AsReadOnly(); } }