# MoveJoint 失败样本六轴限值与 ActualSendJerkStats 对比

记录时间：2026-05-05

## 1. 目的

本文档固定记录以下三类证据，避免后续继续混用测试基线、旧文档结论和当前运行目录中的真实模型数据：

- 当前运行目录 `.robot` 模型中的六轴基础 `velocity / acceleration / jerk`
- 现场示教器读取到的六轴 `velocity / acceleration / jerk`
- 当前运行目录 `RobotConfig.json` 中的 `acc_limit / jerk_limit`
- 当前失败样本 `ActualSendJerkStats.txt` 中的逐轴实发跃度峰值

本次样本对应目录：

- `.robot`：`src/Flyshot.Server.Host/bin/Debug/net8.0/Config/Models/LR_Mate_200iD_7L.robot`
- 配置：`src/Flyshot.Server.Host/bin/Debug/net8.0/Config/RobotConfig.json`
- 实发跃度：`src/Flyshot.Server.Host/bin/Debug/net8.0/Config/Data/move-joint/DenseSend/20260505_203416_563/ActualSendJerkStats.txt`
- 抓包：`src/Flyshot.Server.Host/bin/Debug/net8.0/Config/Data/move-joint/DenseSend/20260505_203416_563/移动点 跃度过大.pcap`

## 2. 当前运行模型的真实六轴限值

当前仓库运行时通过 `RobotModelLoader.LoadProfile(...)` 从 `.robot` 中读取每轴 `limit.velocity / limit.acceleration / limit.jerk`，然后只对加速度和 jerk 叠加 `RobotConfig.json` 的全局倍率：

- `velocity_eff = velocity_base`
- `acceleration_eff = acceleration_base * acc_limit`
- `jerk_eff = jerk_base * jerk_limit`

当前运行目录 `RobotConfig.json` 中：

- `acc_limit = 0.74`
- `jerk_limit = 0.74`

按当前运行目录真实模型解出的六轴基础值与生效值如下：

| Joint | vel_base | acc_base | jerk_base | vel_eff | acc_eff | jerk_eff(rad/s^3) | jerk_eff(deg/s^3) |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| Joint1 | 6.45 | 26.90 | 224.22 | 6.45 | 19.9060 | 165.9228 | 9506.6762 |
| Joint2 | 5.41 | 22.54 | 187.86 | 5.41 | 16.6796 | 139.0164 | 7965.0530 |
| Joint3 | 7.15 | 29.81 | 248.46 | 7.15 | 22.0594 | 183.8604 | 10534.4249 |
| Joint4 | 9.59 | 39.99 | 333.30 | 9.59 | 29.5926 | 246.6420 | 14131.5457 |
| Joint5 | 9.51 | 39.63 | 330.27 | 9.51 | 29.3262 | 244.3998 | 14003.0771 |
| Joint6 | 17.45 | 72.72 | 606.01 | 17.45 | 53.8128 | 448.4474 | 25694.1434 |

重要结论：

- 当前运行目录中，`Joint1.jerk_base` 不是测试基线里常见的 `272.7`，而是 `224.22`。
- 因此当前样本的 `Joint1` 生效 jerk 上限应按 `224.22 * 0.74 = 165.9228 rad/s^3` 计算。

## 3. 示教器读取到的实际机器人限值

2026-05-06 现场从机器人示教器读取到的速度、加速度与加加速度限制如下。示教器显示口径为角度制；下表同时记录换算后的弧度制，便于与 `.robot` / `RobotProfile` 中的基础限值直接对照。

换算公式：

- `rad = deg * π / 180`

| Joint | velocity(deg/s) | velocity(rad/s) | acceleration(deg/s^2) | acceleration(rad/s^2) | jerk(deg/s^3) | jerk(rad/s^3) |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| Joint1 | 370 | 6.457718 | 1541.667 | 26.907165 | 12847.223 | 224.226341 |
| Joint2 | 310 | 5.410521 | 1291.667 | 22.543842 | 10763.889 | 187.865303 |
| Joint3 | 410 | 7.155850 | 1708.333 | 29.816036 | 14236.111 | 248.467010 |
| Joint4 | 550 | 9.599311 | 2291.667 | 39.997135 | 19097.223 | 333.309419 |
| Joint5 | 545 | 9.512044 | 2270.833 | 39.633513 | 18923.611 | 330.279318 |
| Joint6 | 1000 | 17.453293 | 4166.667 | 72.722058 | 34722.223 | 606.017115 |

这组数据的含义：

- 示教器读取值与当前运行 `.robot` 中的 `velocity_base / acceleration_base / jerk_base` 基本一致，可作为实际机器人基础限值证据。
- 它还没有叠加当前 `RobotConfig.json` 的 `acc_limit = 0.74` 与 `jerk_limit = 0.74`；若用于本次失败样本比较，仍应使用第 2 节中的 `acc_eff / jerk_eff` 作为生效上限。

## 4. ActualSendJerkStats 的单位边界

`ActualSendJerkStats.txt` 的真实输入不是弧度，而是 J519 下发用的角度制关节目标：

1. `SampleDenseJointTrajectoryDegrees(...)` 先把轨迹点从 `rad` 转成 `deg`
2. `BuildDenseSendJointRow(...)` 把这组角度制关节写入 `ActualSendJointTraj.txt`
3. `BuildDenseSendJerkRow(...)` 再直接基于这组角度制关节做三阶差分

2026-05-06 之后，`ActualSendJointTraj.txt` 第一列和 `ActualSendJerkStats.txt` 的 `dt` 都使用 J519 实发时间；若需要查看被 `speed_ratio` 缩放后的原轨迹采样时间，应读取同目录的 `ActualSendTiming.txt`。因此当前这份 `ActualSendJerkStats.txt` 的逐轴跃度应按以下方式理解：

- 文本中的数值口径：`deg/s^3`
- 若要与 `.robot` / `RobotProfile` 中的 jerk limit 比较，需要先换算为 `rad/s^3`
- 换算公式：`jerk_rad = jerk_deg * π / 180`

## 5. 全文件逐轴最大跃度对比

扫描整份 `ActualSendJerkStats.txt` 后，各轴绝对值最大跃度如下：

| Joint | peak window(s) | peak line | peak actual(deg/s^3) | peak actual(rad/s^3) | jerk_eff(rad/s^3) | peak/limit |
| --- | --- | ---: | ---: | ---: | ---: | ---: |
| Joint1 | `1.056 -> 1.064` | 133 | 21868.115990 | 381.670625 | 165.922800 | 2.3003 |
| Joint2 | `1.056 -> 1.064` | 133 | 40.271793 | 0.702875 | 139.016400 | 0.0051 |
| Joint3 | `1.056 -> 1.064` | 133 | 98.314401 | 1.715910 | 183.860400 | 0.0093 |
| Joint4 | `1.056 -> 1.064` | 133 | 0.207266 | 0.003617 | 246.642000 | 0.0000 |
| Joint5 | `1.056 -> 1.064` | 133 | 26.759688 | 0.467045 | 244.399800 | 0.0019 |
| Joint6 | `1.056 -> 1.064` | 133 | 2.328736 | 0.040644 | 448.447400 | 0.0001 |

结论非常明确：

- 全文件范围内，只有 `Joint1` 的实发跃度显著超过当前生效 jerk 上限。
- 其余 5 个轴即使取全文件峰值，也远低于各自当前生效 jerk limit。
- 当前样本本质上是一个“J1 主导”的跃度问题，而不是六轴普遍同时逼近上限。

## 6. 报警窗口逐轴对比

结合抓包与 J519 序号，报警前最后一个关键窗口是：

- `seq=41552`
- 轨迹时间窗口：`0.296 -> 0.304s`
- `ActualSendJerkStats.txt` 行号：38

该窗口逐轴跃度如下：

| Joint | alarm window jerk(deg/s^3) | alarm window jerk(rad/s^3) | jerk_eff(rad/s^3) | alarm/limit |
| --- | ---: | ---: | ---: | ---: |
| Joint1 | -20395.713579 | 355.972355 | 165.922800 | 2.1454 |
| Joint2 | -37.560252 | 0.655550 | 139.016400 | 0.0047 |
| Joint3 | 91.694793 | 1.600376 | 183.860400 | 0.0087 |
| Joint4 | -0.193310 | 0.003374 | 246.642000 | 0.0000 |
| Joint5 | 24.957931 | 0.435598 | 244.399800 | 0.0018 |
| Joint6 | 2.171939 | 0.037907 | 448.447400 | 0.0001 |

该窗口的直接结论与全局扫描一致：

- 机器人开始报警的 `0.296 -> 0.304s` 窗口里，真正越限的仍然只有 `Joint1`
- `Joint1` 在报警窗口内已经达到当前生效 jerk limit 的 `2.1454x`
- 其余 5 轴在同一窗口仍远低于生效 jerk 上限

## 7. 报警窗口与全局峰值窗口的关系

本次样本不能简单理解为“最大峰值出现的位置就是首次报警位置”。

当前证据表明：

- 首次报警相关窗口在 `0.296 -> 0.304s`
- 全文件最大的 J1 跃度峰值出现在更后面的 `1.056 -> 1.064s`

这说明至少有两件事需要分开：

1. 机器人第一次进入异常态时，`Joint1` 已经在 `0.296 -> 0.304s` 超限约 `2.15x`
2. 即便忽略第一次报警，后续轨迹中仍存在更高的 J1 跃度峰值，说明当前 `MoveJoint` 临时轨迹整体都偏激，不只是单个孤立点异常

## 8. 当前可落地的结论

基于当前运行目录的真实模型、配置和实发跃度文件，本次失败样本可以先固定为下面这组结论：

- 当前运行模型 `Joint1.jerk_base = 224.22`，不是 `272.7`
- 现场示教器读取到的 `Joint1.jerk = 12847.223 deg/s^3 = 224.226341 rad/s^3`，与当前运行模型基础值一致
- 当前样本 `jerk_limit = 0.74`，所以 `Joint1.jerk_eff = 165.9228 rad/s^3`
- `ActualSendJerkStats.txt` 需要按 `deg/s^3` 理解，再换算成 `rad/s^3` 后与模型 jerk limit 对比
- 无论看报警窗口还是看全文件峰值，越限主体都只有 `Joint1`
- 报警窗口 `0.296 -> 0.304s` 中，`Joint1` 已经约为当前生效 jerk 上限的 `2.1454x`
- 全文件最大峰值窗口 `1.056 -> 1.064s` 中，`Joint1` 约为当前生效 jerk 上限的 `2.3003x`

因此当前最合理的根因指向仍然是：

- `MoveJoint` 临时轨迹生成得过于激进
- 当前问题首先应按 `Joint1` 的 jerk 约束失配来处理
- 暂时没有证据支持“六轴普遍一起逼近限制”或“网络链路导致跃度统计失真”这类解释
