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