using System.Collections.Generic; using System.Collections.ObjectModel; using MultiWheelC.TrajectoryPlanning.CoarsePath; using Newtonsoft.Json; namespace MultiWheelC.TrajectoryPlanning.PathSmoothing.Test; /// 一个可复现的快速粗路径夹具及其地图、车辆和方向段快照。 public sealed class SmoothingScenarioFixture { internal SmoothingScenarioFixture(SmoothingFixtureRecord record, bool fingerprintCurrent) { Record = record; Id = record.Id; FixtureVersion = record.FixtureVersion; ConfigurationFingerprint = record.ConfigurationFingerprint; IsConfigurationFingerprintCurrent = fingerprintCurrent; Path = ToPath(record.Path); Segments = ToSegments(record.Segments); } /// 稳定英文场景标识。 public string Id { get; } /// 夹具自身的正版本号。 public int FixtureVersion { get; } /// 由夹具输入生成的稳定 SHA-256 指纹。 public string ConfigurationFingerprint { get; } /// 存储指纹是否与当前夹具内容一致。 public bool IsConfigurationFingerprintCurrent { get; } /// 快速比较使用的不可变粗路径点。 public IReadOnlyList Path { get; } /// 覆盖粗路径的不可变方向段。 public IReadOnlyList Segments { get; } internal SmoothingFixtureRecord Record { get; } private static IReadOnlyList ToPath(IReadOnlyList source) { var result = new List(source.Count); for (int index = 0; index < source.Count; index++) { SmoothingFixturePathPoint point = source[index]; result.Add(new CoarsePathPoint( point.XMeters, point.YMeters, point.HeadingRadians, point.UnwrappedHeadingRadians, point.ArcLengthMeters, point.Direction, point.VehicleCurvaturePerMeter, point.BodyClearanceMeters, point.IsGearSwitchPoint, point.Source)); } return new ReadOnlyCollection(result); } private static IReadOnlyList ToSegments(IReadOnlyList source) { var result = new List(source.Count); for (int index = 0; index < source.Count; index++) { SmoothingFixtureSegment segment = source[index]; result.Add(new PathSegment(segment.SegmentIndex, segment.Direction, segment.StartIndex, segment.EndIndex, segment.StartsAtGearSwitch, segment.EndsAtGearSwitch)); } return new ReadOnlyCollection(result); } } internal sealed class SmoothingFixtureDocument { [JsonProperty("schemaVersion")] public int SchemaVersion { get; set; } [JsonProperty("scenarios")] public List Scenarios { get; set; } = new List(); } internal sealed class SmoothingFixtureRecord { [JsonProperty("id")] public string Id { get; set; } [JsonProperty("fixtureVersion")] public int FixtureVersion { get; set; } [JsonProperty("configurationFingerprint")] public string ConfigurationFingerprint { get; set; } [JsonProperty("map")] public SmoothingFixtureMap Map { get; set; } [JsonProperty("vehicle")] public SmoothingFixtureVehicle Vehicle { get; set; } [JsonProperty("planningConfiguration")] public SmoothingFixturePlanningConfiguration PlanningConfiguration { get; set; } [JsonProperty("path")] public List Path { get; set; } = new List(); [JsonProperty("segments")] public List Segments { get; set; } = new List(); } internal sealed class SmoothingFixtureMap { [JsonProperty("xMinMm")] public float XMinMm { get; set; } [JsonProperty("xMaxMm")] public float XMaxMm { get; set; } [JsonProperty("yMinMm")] public float YMinMm { get; set; } [JsonProperty("yMaxMm")] public float YMaxMm { get; set; } [JsonProperty("resolutionMm")] public float ResolutionMm { get; set; } [JsonProperty("obstacles")] public List Obstacles { get; set; } = new List(); } internal sealed class SmoothingFixtureObstacle { [JsonProperty("kind")] public string Kind { get; set; } [JsonProperty("xMinMm")] public float XMinMm { get; set; } [JsonProperty("xMaxMm")] public float XMaxMm { get; set; } [JsonProperty("yMinMm")] public float YMinMm { get; set; } [JsonProperty("yMaxMm")] public float YMaxMm { get; set; } [JsonProperty("centerXMm")] public float CenterXMm { get; set; } [JsonProperty("centerYMm")] public float CenterYMm { get; set; } [JsonProperty("radiusMm")] public float RadiusMm { get; set; } } internal sealed class SmoothingFixtureVehicle { [JsonProperty("lengthMeters")] public double LengthMeters { get; set; } [JsonProperty("widthMeters")] public double WidthMeters { get; set; } [JsonProperty("safetyMarginMeters")] public double SafetyMarginMeters { get; set; } [JsonProperty("maximumCurvaturePerMeter")] public double MaximumCurvaturePerMeter { get; set; } } /// 产生夹具粗路径时使用的 Hybrid A* 配置快照;仅用于溯源和指纹验证,不参与快速夹具加载时的规划。 internal sealed class SmoothingFixturePlanningConfiguration { [JsonProperty("primitiveLengthMeters")] public double PrimitiveLengthMeters { get; set; } [JsonProperty("integrationStepMeters")] public double IntegrationStepMeters { get; set; } [JsonProperty("maximumCollisionCheckStepMeters")] public double MaximumCollisionCheckStepMeters { get; set; } [JsonProperty("headingResolutionRadians")] public double HeadingResolutionRadians { get; set; } [JsonProperty("curvatureLevelCount")] public int CurvatureLevelCount { get; set; } [JsonProperty("goalPositionToleranceMeters")] public double GoalPositionToleranceMeters { get; set; } [JsonProperty("goalHeadingToleranceRadians")] public double GoalHeadingToleranceRadians { get; set; } [JsonProperty("maximumExpandedNodes")] public int MaximumExpandedNodes { get; set; } [JsonProperty("searchTimeoutSeconds")] public double SearchTimeoutSeconds { get; set; } [JsonProperty("heuristicWeight")] public double HeuristicWeight { get; set; } [JsonProperty("reverseCostMultiplier")] public double ReverseCostMultiplier { get; set; } [JsonProperty("gearSwitchPenaltyMeters")] public double GearSwitchPenaltyMeters { get; set; } [JsonProperty("curvatureMagnitudeWeight")] public double CurvatureMagnitudeWeight { get; set; } [JsonProperty("curvatureChangePenaltyMetersPerLevel")] public double CurvatureChangePenaltyMetersPerLevel { get; set; } [JsonProperty("clearanceCostWeight")] public double ClearanceCostWeight { get; set; } [JsonProperty("clearanceCostDistanceMeters")] public double ClearanceCostDistanceMeters { get; set; } [JsonProperty("allowReverse")] public bool AllowReverse { get; set; } } internal sealed class SmoothingFixturePathPoint { [JsonProperty("xMeters")] public double XMeters { get; set; } [JsonProperty("yMeters")] public double YMeters { get; set; } [JsonProperty("headingRadians")] public double HeadingRadians { get; set; } [JsonProperty("unwrappedHeadingRadians")] public double UnwrappedHeadingRadians { get; set; } [JsonProperty("arcLengthMeters")] public double ArcLengthMeters { get; set; } [JsonProperty("direction")] public TravelDirection Direction { get; set; } [JsonProperty("vehicleCurvaturePerMeter")] public double VehicleCurvaturePerMeter { get; set; } [JsonProperty("bodyClearanceMeters")] public double BodyClearanceMeters { get; set; } [JsonProperty("isGearSwitchPoint")] public bool IsGearSwitchPoint { get; set; } [JsonProperty("source")] public CoarsePathPointSource Source { get; set; } } internal sealed class SmoothingFixtureSegment { [JsonProperty("segmentIndex")] public int SegmentIndex { get; set; } [JsonProperty("direction")] public TravelDirection Direction { get; set; } [JsonProperty("startIndex")] public int StartIndex { get; set; } [JsonProperty("endIndex")] public int EndIndex { get; set; } [JsonProperty("startsAtGearSwitch")] public bool StartsAtGearSwitch { get; set; } [JsonProperty("endsAtGearSwitch")] public bool EndsAtGearSwitch { get; set; } }