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