using System.Text.Json.Serialization; namespace Flyshot.Core.Domain; /// /// 描述机器人运动学链所需的完整关节几何信息,从现场固化的机器人 JSON 中提取。 /// /// 为什么与 RobotProfile 分开? /// --- /// RobotProfile 只存规划侧需要的限速和 couple 元数据,是"规划约束视图"。 /// RobotKinematicsModel 存的是几何链(origin、axis、变换顺序),是"运动学视图"。 /// 两者生命周期和用途不同,分开可以避免规划层被迫依赖完整几何数据。 /// public sealed class RobotKinematicsModel { /// /// 初始化一份已验证的运动学模型。 /// public RobotKinematicsModel(string name, IEnumerable joints) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("机器人名称不能为空。", nameof(name)); } ArgumentNullException.ThrowIfNull(joints); var copiedJoints = joints.ToArray(); if (copiedJoints.Length == 0) { throw new ArgumentException("关节列表不能为空。", nameof(joints)); } Name = name; Joints = copiedJoints; } /// /// 获取机器人名称。 /// [JsonPropertyName("name")] public string Name { get; } /// /// 获取按运动学链顺序排列的关节几何列表。 /// [JsonPropertyName("joints")] public IReadOnlyList Joints { get; } } /// /// 描述单个关节的几何属性,用于正运动学计算。 /// public sealed class RobotJointGeometry { /// /// 初始化一份已验证的关节几何描述。 /// public RobotJointGeometry( string name, string parent, string child, int jointType, double[] axis, double[] originXyz, double[] originQuatXyzw, string? coupleMaster = null, double coupleMultiplier = 0.0, double coupleOffset = 0.0) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("关节名称不能为空。", nameof(name)); } if (string.IsNullOrWhiteSpace(parent)) { throw new ArgumentException("父节点名称不能为空。", nameof(parent)); } if (string.IsNullOrWhiteSpace(child)) { throw new ArgumentException("子节点名称不能为空。", nameof(child)); } if (axis is null || axis.Length != 3) { throw new ArgumentException("关节轴必须是长度为 3 的数组。", nameof(axis)); } if (originXyz is null || originXyz.Length != 3) { throw new ArgumentException("原点平移必须是长度为 3 的数组。", nameof(originXyz)); } if (originQuatXyzw is null || originQuatXyzw.Length != 4) { throw new ArgumentException("原点旋转四元数必须是长度为 4 的数组(xyzw)。", nameof(originQuatXyzw)); } Name = name; Parent = parent; Child = child; JointType = jointType; Axis = (double[])axis.Clone(); OriginXyz = (double[])originXyz.Clone(); OriginQuatXyzw = (double[])originQuatXyzw.Clone(); CoupleMaster = coupleMaster; CoupleMultiplier = coupleMultiplier; CoupleOffset = coupleOffset; } /// /// 获取关节名称。 /// [JsonPropertyName("name")] public string Name { get; } /// /// 获取父连杆名称。 /// [JsonPropertyName("parent")] public string Parent { get; } /// /// 获取子连杆名称。 /// [JsonPropertyName("child")] public string Child { get; } /// /// 获取关节类型:0=fixed, 1=prismatic, 2=revolute。 /// [JsonPropertyName("jointType")] public int JointType { get; } /// /// 获取关节旋转轴(单位向量)。 /// [JsonPropertyName("axis")] public double[] Axis { get; } /// /// 获取关节原点平移 [x, y, z]。 /// [JsonPropertyName("originXyz")] public double[] OriginXyz { get; } /// /// 获取关节原点旋转四元数 [x, y, z, w]。 /// [JsonPropertyName("originQuatXyzw")] public double[] OriginQuatXyzw { get; } /// /// 获取耦合主关节名称(如无则为 null)。 /// [JsonPropertyName("coupleMaster")] public string? CoupleMaster { get; } /// /// 获取耦合乘数。 /// [JsonPropertyName("coupleMultiplier")] public double CoupleMultiplier { get; } /// /// 获取耦合偏移。 /// [JsonPropertyName("coupleOffset")] public double CoupleOffset { get; } }