using System.Text.Json.Serialization; namespace Flyshot.Core.Domain; /// /// 描述规划与运行时编排共同使用的机器人模型契约。 /// public sealed class RobotProfile { /// /// 使用已校验的关节约束与耦合元数据初始化机器人画像。 /// public RobotProfile( string name, string modelPath, int degreesOfFreedom, IEnumerable jointLimits, IEnumerable jointCouplings, TimeSpan servoPeriod, TimeSpan triggerPeriod) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("Robot profile name is required.", nameof(name)); } if (string.IsNullOrWhiteSpace(modelPath)) { throw new ArgumentException("Robot profile model path is required.", nameof(modelPath)); } if (degreesOfFreedom <= 0) { throw new ArgumentOutOfRangeException(nameof(degreesOfFreedom), "Degrees of freedom must be positive."); } if (servoPeriod <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(servoPeriod), "Servo period must be positive."); } if (triggerPeriod <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(triggerPeriod), "Trigger period must be positive."); } ArgumentNullException.ThrowIfNull(jointLimits); ArgumentNullException.ThrowIfNull(jointCouplings); // 先对集合做一次快照,避免下游直接原地修改领域状态。 var copiedJointLimits = jointLimits.ToArray(); var copiedJointCouplings = jointCouplings.ToArray(); if (copiedJointLimits.Length != degreesOfFreedom) { throw new ArgumentException("Joint limit count must match degrees of freedom.", nameof(jointLimits)); } Name = name; ModelPath = modelPath; DegreesOfFreedom = degreesOfFreedom; JointLimits = copiedJointLimits; JointCouplings = copiedJointCouplings; ServoPeriod = servoPeriod; TriggerPeriod = triggerPeriod; } /// /// 获取对运行时其余模块暴露的机器人画像名称。 /// [JsonPropertyName("name")] public string Name { get; } /// /// 获取机器人模型文件的来源路径。 /// [JsonPropertyName("modelPath")] public string ModelPath { get; } /// /// 获取当前生效的旋转关节自由度数量。 /// [JsonPropertyName("degreesOfFreedom")] public int DegreesOfFreedom { get; } /// /// 获取按关节校验后的运动学约束。 /// [JsonPropertyName("jointLimits")] public IReadOnlyList JointLimits { get; } /// /// 获取从机器人模型解析出的可选关节耦合元数据。 /// [JsonPropertyName("jointCouplings")] public IReadOnlyList JointCouplings { get; } /// /// 获取运行时使用的伺服调度周期。 /// [JsonPropertyName("servoPeriod")] public TimeSpan ServoPeriod { get; } /// /// 获取飞拍事件对齐使用的触发调度周期。 /// [JsonPropertyName("triggerPeriod")] public TimeSpan TriggerPeriod { get; } } /// /// 描述规划器所需的单个旋转关节约束集合。 /// public sealed class JointLimit { /// /// 初始化一个已校验的关节约束记录。 /// public JointLimit(string jointName, double velocityLimit, double accelerationLimit, double jerkLimit) { if (string.IsNullOrWhiteSpace(jointName)) { throw new ArgumentException("Joint name is required.", nameof(jointName)); } if (velocityLimit <= 0.0) { throw new ArgumentOutOfRangeException(nameof(velocityLimit), "Velocity limit must be positive."); } if (accelerationLimit <= 0.0) { throw new ArgumentOutOfRangeException(nameof(accelerationLimit), "Acceleration limit must be positive."); } if (jerkLimit <= 0.0) { throw new ArgumentOutOfRangeException(nameof(jerkLimit), "Jerk limit must be positive."); } JointName = jointName; VelocityLimit = velocityLimit; AccelerationLimit = accelerationLimit; JerkLimit = jerkLimit; } /// /// 获取该约束对应的关节名称。 /// [JsonPropertyName("jointName")] public string JointName { get; } /// /// 获取关节空间单位下的速度上限。 /// [JsonPropertyName("velocityLimit")] public double VelocityLimit { get; } /// /// 获取关节空间单位下的加速度上限。 /// [JsonPropertyName("accelerationLimit")] public double AccelerationLimit { get; } /// /// 获取关节空间单位下的跃度上限。 /// [JsonPropertyName("jerkLimit")] public double JerkLimit { get; } } /// /// 描述在运动学计算或轨迹规划前必须应用的关节耦合规则。 /// public sealed class JointCoupling { /// /// 初始化一个已校验的关节耦合描述。 /// public JointCoupling(string slaveJointName, string masterJointName, double multiplier, double offset) { if (string.IsNullOrWhiteSpace(slaveJointName)) { throw new ArgumentException("Slave joint name is required.", nameof(slaveJointName)); } if (string.IsNullOrWhiteSpace(masterJointName)) { throw new ArgumentException("Master joint name is required.", nameof(masterJointName)); } if (string.Equals(slaveJointName, masterJointName, StringComparison.Ordinal)) { throw new ArgumentException("Slave and master joints must be different."); } SlaveJointName = slaveJointName; MasterJointName = masterJointName; Multiplier = multiplier; Offset = offset; } /// /// 获取从属(被驱动)关节名称。 /// [JsonPropertyName("slaveJointName")] public string SlaveJointName { get; } /// /// 获取主导(驱动)关节名称。 /// [JsonPropertyName("masterJointName")] public string MasterJointName { get; } /// /// 获取作用在主导关节角度上的耦合倍率。 /// [JsonPropertyName("multiplier")] public double Multiplier { get; } /// /// 获取在耦合倍率之后叠加的偏移量。 /// [JsonPropertyName("offset")] public double Offset { get; } }