本文档详细说明逆向运动学求解系统中使用的所有 JSON 文件格式规范。
定义机械结构的拓扑与属性,包括关节类型、位置、约束等信息。
{
"root_name": "Root",
"joints": [
{
"name": "关节名称",
"type": "关节类型",
"offset": [x, y, z],
"parent": "父节点名称或null",
// 其他字段根据关节类型而定
}
]
}-
root_name(String, 必需)- 根节点的名称
- 必须在
joints数组中存在对应的关节
-
joints(Array, 必需)- 关节列表,每个元素为一个关节对象
-
name(String, 必需)- 关节名称,必须唯一
- 用作关节的唯一标识符
-
type(String, 必需)- 关节类型,可选值:
"fixed": 固定关节(无自由度)"revolute": 旋转关节(1自由度)"prismatic": 移动关节(1自由度)"spherical": 球形关节(3自由度)
- 关节类型,可选值:
-
offset(Array[Float, Float, Float], 必需)- 相对父级的静态位移(单位:米)
- 格式:
[x, y, z] - 根节点的
offset通常为[0, 0, 0]
-
parent(String | null, 必需)- 父节点名称
null表示根节点(无父节点)- 必须指向
joints数组中已存在的关节名称
固定关节无需额外字段。
示例:
{
"name": "Root",
"type": "fixed",
"offset": [0, 0, 0],
"parent": null
}-
axis(Array[Float, Float, Float], 必需)- 旋转轴(局部坐标系,不能为零向量。程序会自动归一化)
- 格式:
[x, y, z] - 示例:
[1, 0, 0]表示绕局部 X 轴旋转
-
limits(Array[Float, Float] | null, 可选)- 角度约束范围(单位:弧度)
- 格式:
[min, max] null或省略表示无约束- 示例:
[0.0, 3.14159]表示角度范围 0 到 π 弧度
示例:
{
"name": "Elbow",
"type": "revolute",
"offset": [0, 0, 2.0],
"parent": "Shoulder",
"axis": [1, 0, 0],
"limits": [0.0, 2.5]
}-
axis(Array[Float, Float, Float], 必需)- 移动轴(局部坐标系,不能为零向量。程序会自动归一化)
- 格式:
[x, y, z] - 示例:
[0, 0, 1]表示沿局部 Z 轴移动
-
limits(Array[Float, Float] | null, 可选)- 位移约束范围(单位:米)
- 格式:
[min, max] null或省略表示无约束- 示例:
[0.0, 0.5]表示位移范围 0 到 0.5 米
示例:
{
"name": "Piston",
"type": "prismatic",
"offset": [0, 0, 1.0],
"parent": "Elbow",
"axis": [0, 0, 1],
"limits": [0.0, 0.5]
}limits(Array | null, 可选)- 三个轴的约束范围
- 格式:
[[min, max] | null, [min, max] | null, [min, max] | null] - 每个元素对应一个轴的约束:
[min, max]: 该轴有约束(单位:弧度)null: 该轴无约束
- 整个
limits字段可省略(等同于所有轴无约束) - 示例:
[[-3.14, 3.14], null, [-0.5, 0.5]]表示 X 轴和 Z 轴有约束,Y 轴无约束
示例:
{
"name": "Shoulder",
"type": "spherical",
"offset": [0, 1.5, 0],
"parent": "Root",
"limits": [[-3.14, 3.14], null, [-0.5, 0.5]]
}{
"root_name": "Root",
"joints": [
{
"name": "Root",
"type": "fixed",
"offset": [0, 0, 0],
"parent": null
},
{
"name": "Shoulder",
"type": "spherical",
"offset": [0, 1.5, 0],
"parent": "Root",
"limits": [[-3.14, 3.14], null, [-0.5, 0.5]]
},
{
"name": "Elbow",
"type": "revolute",
"offset": [0, 0, 2.0],
"parent": "Shoulder",
"axis": [1, 0, 0],
"limits": [0.0, 2.5]
},
{
"name": "Piston",
"type": "prismatic",
"offset": [0, 0, 1.0],
"parent": "Elbow",
"axis": [0, 0, 1],
"limits": [0.0, 0.5]
},
{
"name": "EndEffector",
"type": "fixed",
"offset": [0, 0, 0.5],
"parent": "Piston"
}
]
}-
轴向量归一化:
axis字段不能为零向量。系统会自动归一化,但建议在 JSON 中提供归一化的值。 -
父子关系:必须形成有效的树形结构,不能出现循环引用。
-
约束范围:
limits字段为可选,省略表示无约束- 对于 SphericalJoint,
limits数组长度必须为 3,每个元素可以是[min, max]或null
-
单位:
offset: 米- RevoluteJoint
limits: 弧度 - PrismaticJoint
limits: 米 - SphericalJoint
limits: 弧度
定义末端执行器的关键帧,系统会在关键帧之间进行插值生成完整的目标轨迹。
[
{
"frame": 帧号,
"pos": [x, y, z],
"euler": [x, y, z]
},
{
"frame": 帧号,
"pos": [x, y, z],
"euler": [x, y, z]
}
]-
frame(Integer, 必需)- 关键帧帧号(从 0 开始)
- 必须按帧号顺序排列(系统会自动排序)
-
pos(Array[Float, Float, Float], 必需)- 世界坐标系中的位置(单位:米)
- 格式:
[x, y, z] - 示例:
[1.0, 1.0, 1.0]表示位置 (1, 1, 1) 米
-
euler(Array[Float, Float, Float], 必需)- 世界坐标系中的姿态欧拉角(单位:度,顺序:XYZ)
- 格式:
[x, y, z] - 旋转顺序:先绕 X 轴旋转,再绕 Y 轴,最后绕 Z 轴
- 示例:
[90.0, 0.0, 45.0]表示绕 X 轴旋转 90 度,绕 Y 轴旋转 0 度,绕 Z 轴旋转 45 度
[
{
"frame": 0,
"pos": [0.0, 0.0, 0.0],
"euler": [0.0, 0.0, 0.0]
},
{
"frame": 80,
"pos": [1.0, 1.0, 1.0],
"euler": [90.0, 0.0, 45.0]
},
{
"frame": 160,
"pos": [1.0, -1.0, 1.0],
"euler": [-90.0, 45.0, 0.0]
},
{
"frame": 240,
"pos": [2.5, 0.0, 1.0],
"euler": [0.0, 0.0, 0.0]
}
]-
欧拉角顺序:固定为 XYZ 顺序,不可更改。
-
单位:
pos: 米euler: 度(系统内部会转换为弧度)
-
插值:
- 系统会在关键帧之间进行线性插值(位置)和球面线性插值(姿态,SLERP)
- 第一个关键帧之前和最后一个关键帧之后使用最近的关键帧值
-
帧号:建议从 0 开始,按递增顺序排列。
记录求解完成后的关节运动数据,按帧记录每个关节的局部变量。
{
"frames": [
{
"frame": 帧号,
"joints": {
"关节名称": {
"type": "关节类型",
// 其他字段根据关节类型而定
}
}
}
]
}frames(Array, 必需)- 按帧号顺序排列的帧数据
-
frame(Integer, 必需)- 帧号(从 0 开始)
-
joints(Object, 必需)- 关节名称到关节数据的映射
- 仅包含有自由度的关节(FixedJoint 不参与导出)
{
"type": "revolute",
"angle": 角度值
}type(String):"revolute"angle(Float): 角度(单位:弧度)
示例:
{
"type": "revolute",
"angle": 1.571
}{
"type": "prismatic",
"displacement": 位移值
}type(String):"prismatic"displacement(Float): 位移(单位:米)
示例:
{
"type": "prismatic",
"displacement": 0.25
}{
"type": "spherical",
"euler": [x, y, z],
"quaternion": [w, x, y, z]
}type(String):"spherical"euler(Array[Float, Float, Float]): 欧拉角(单位:弧度)quaternion(Array[Float, Float, Float, Float]): 四元数(格式:[w, x, y, z])
示例:
{
"type": "spherical",
"euler": [0.523, 0.0, 0.785],
"quaternion": [0.924, 0.383, 0.0, 0.0]
}{
"frames": [
{
"frame": 0,
"joints": {
"Shoulder": {
"type": "spherical",
"euler": [0.523, 0.0, 0.785],
"quaternion": [0.924, 0.383, 0.0, 0.0]
},
"Elbow": {
"type": "revolute",
"angle": 1.571
},
"Piston": {
"type": "prismatic",
"displacement": 0.25
}
}
},
{
"frame": 1,
"joints": {
"Shoulder": {
"type": "spherical",
"euler": [0.628, 0.087, 0.890],
"quaternion": [0.918, 0.396, 0.0, 0.0]
},
"Elbow": {
"type": "revolute",
"angle": 1.623
},
"Piston": {
"type": "prismatic",
"displacement": 0.27
}
}
}
]
}-
单位:
- RevoluteJoint
angle: 弧度 - PrismaticJoint
displacement: 米 - SphericalJoint
euler: 弧度
- RevoluteJoint
-
四元数格式:
[w, x, y, z],其中w是标量部分。 -
FixedJoint:固定关节不参与导出(无变量)。
-
帧顺序:
frames数组按帧号顺序排列,从 0 开始。
建议将 JSON 文件放置在以下位置:
- skeleton.json:
data/skeleton.json - targets.json:
data/targets.json - animation.json:
data/animation.json(导出文件)
打包为可执行程序时,如果 data/ 目录下存在以下文件,它们会被自动包含到可执行文件中,作为默认文件:
skeleton.json- 骨骼定义文件targets.json- 目标轨迹文件
如果这些文件不存在,打包仍可正常进行,用户可以在运行时通过GUI界面自行导入文件。
- JSON 格式错误:确保文件是有效的 JSON 格式
- 缺少必需字段:检查所有必需字段是否存在
- 类型错误:确保字段类型正确(如
frame必须是整数) - 父子关系错误:确保
parent字段指向存在的关节 - 轴向量非单位向量:系统会自动归一化,但建议提供单位向量
可以使用 JSON Schema 验证工具验证文件格式,或使用系统提供的加载函数进行验证(加载失败时会抛出异常)。
- v1.0.0 (2024-11-13): 初始版本,基于 SPEC.md 规范
docs/SPEC.md: 完整的设计规范文档docs/QUICKSTART.md: 快速开始指南docs/PROJECT_STRUCTURE.md: 项目结构说明