Files
FlyShotHost/src/Flyshot.Core.Domain/RobotKinematicsModel.cs
yunxiao.zhu c6829d214a feat(*): 添加 J519 实发重采样与 JSON 机型模型
* 新增 J519 实发采样器,按 8ms 周期生成 timing/jerk 诊断行并完成 rad->deg 转换
* 兼容层产物导出补充 speedRatio,规划编排补齐 smoothStartStopTiming 与日志透传
* 配置与机型加载切换到运行目录 JSON 模型,并补齐 7L 展开模型与相关单元测试
2026-05-07 17:08:32 +08:00

173 lines
5.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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