using System; using System.Collections.Generic; using System.Collections.ObjectModel; namespace MultiWheelC.TrajectoryPlanning.CoarsePath.Search; /// /// 一条经连续碰撞检查的恒曲率运动原语。 /// 位置和长度单位为 m,航向单位为 rad,曲率单位为 1/m; 不包含起点,只包含按积分顺序产生的后续点。 /// public sealed class MotionPrimitive { /// /// 创建不可变运动原语。 /// 参数:start 为原语起点;direction 为行驶方向;curvaturePerMeter 为恒定曲率;actualLengthMeters 为已实际行驶长度; /// points 与 bodyClearancesMeters 按同一索引保存内部积分位姿和对应的车体净空;isGoalTruncation 表示末点是否首次命中目标容差。 /// public MotionPrimitive( Pose2D start, TravelDirection direction, double curvaturePerMeter, double actualLengthMeters, IEnumerable points, IEnumerable bodyClearancesMeters, bool isGoalTruncation) { if (start == null) throw new ArgumentNullException(nameof(start)); if (points == null) throw new ArgumentNullException(nameof(points)); if (bodyClearancesMeters == null) throw new ArgumentNullException(nameof(bodyClearancesMeters)); var copiedPoints = new List(points); var copiedClearances = new List(bodyClearancesMeters); if (copiedPoints.Count != copiedClearances.Count) throw new ArgumentException("The point and clearance counts must match.", nameof(bodyClearancesMeters)); Start = start; Direction = direction; CurvaturePerMeter = curvaturePerMeter; ActualLengthMeters = actualLengthMeters; Points = new ReadOnlyCollection(copiedPoints); BodyClearancesMeters = new ReadOnlyCollection(copiedClearances); End = copiedPoints.Count == 0 ? start : copiedPoints[copiedPoints.Count - 1]; IsGoalTruncation = isGoalTruncation; } /// 原语起始车辆几何中心位姿。 public Pose2D Start { get; } /// 原语最后一个积分点;零长度终点候选时等于 public Pose2D End { get; } /// 原语对应的行驶方向。 public TravelDirection Direction { get; } /// 原语全程采用的恒定车辆曲率,单位 1/m。 public double CurvaturePerMeter { get; } /// 的实际行驶弧长,单位 m。 public double ActualLengthMeters { get; } /// 不含起点的连续积分位姿,只读且按行驶顺序排列。 public IReadOnlyList Points { get; } /// 一一对应的扩大车体保守净空下界,单位 m。 public IReadOnlyList BodyClearancesMeters { get; } /// 末点是否因首次满足目标位置、航向和方向约束而截断。 public bool IsGoalTruncation { get; } }