Files
FlyShotHost/docs/fanuc-10010-state-frame.md
yunxiao.zhu af65ca03a0 feat(compat): 补齐飞拍执行等待与 FANUC 状态驱动链路
- 为 ExecuteFlyShotTraj 补齐 wait 语义,并让 move_to_start
  先完成临时 PTP 运动后再启动正式飞拍轨迹
- 将 J519 命令发送改为由机器人 UDP status sequence 驱动,
  避免在未收到状态包时主动发周期命令
- 将 10010 状态通道关节字段统一按 JointRadians 命名,
  同步更新运行时读取逻辑与协议测试
- 新增 FANUC 10010 状态帧、流运动手册和 Python client
  逆向文档,并更新 README 与兼容需求说明
- 补充兼容层编排测试与 HTTP 集成测试,覆盖 wait 和
  move_to_start 串行化行为
2026-05-03 19:29:31 +08:00

7.0 KiB
Raw Blame History

FANUC TCP 10010 状态帧字段说明

本文档整理当前现场真实抓包中 TCP 10010 状态通道的已确认字段布局,并明确哪些结论已经由抓包和代码验证,哪些仍然只是工作假设。

读取时间2026-05-03

1. 结论范围

本文基于以下证据整理:

  • ../analysis/UTTC_20260428_packet_validation.md
  • ../analysis/J519_stream_motion_analysis.md
  • Rvbust/uttc-20260428/20260428.pcap
  • src/Flyshot.Runtime.Fanuc/Protocol/FanucStateProtocol.cs
  • tests/Flyshot.Core.Tests/FanucProtocolTests.cs

当前结论仅覆盖现场已确认的 R30iB + RVBUSTSM 这一路状态通道行为,不提前推广为所有 FANUC 机型或所有旧版本协议的通用结论。

2. 通道性质

真实抓包显示,TCP 10010 是控制柜到上位机的单向状态流:

  • 上位机先主动建立 TCP 连接。
  • 建连后,带应用层 payload 的业务包全部来自 192.168.10.11:10010 -> 192.168.10.10:41726
  • 上位机在该通道上只回 TCP ACK,没有观察到应用层请求体。

因此当前实现应把 10010 当作“持续推送的固定长度状态帧”处理,而不是像 TCP 10012 那样按请求/响应语义建模。

3. 整体布局

当前现场抓包确认,状态帧固定为 90B

doz                 3 bytes
length              u32 = 90
msg_id              u32
pose[6]             f32
joint_or_ext[9]     f32
tail[4]             u32
zod                 3 bytes

其中:

  • 帧头 magic 固定为 doz
  • 帧尾 magic 固定为 zod
  • 长度字段固定为 0x5a,即 90
  • 当前全量抓包中 msg_id 恒为 0
  • tail[4] 当前全量抓包中恒为 (2, 0, 0, 1)

4. 样例帧

以下样例帧来自 20260428.pcap 中首条 tcp.port == 10010 && tcp.len > 0 的 payload

646f7a0000005a000000004388a23243f1ed7f43e9de6bc265031ec2b33cc3c278e0153f8742f53c3f128dbc929529bc7861d63cb0184c3c1ca1a7000000000000000000000000000000020000000000000000000000017a6f64

对应解析值:

  • pose[6]
    • 273.26715
    • 483.85544
    • 467.73764
    • -57.253044
    • -89.618675
    • -62.21883
  • joint_or_ext[9]
    • 1.0567309
    • 0.011662138
    • -0.01789339
    • -0.015160045
    • 0.02149596
    • 0.009560025
    • 0
    • 0
    • 0
  • tail[4]
    • 2
    • 0
    • 0
    • 1

5. 正式字段表

偏移 长度 类型 样例值(hex) 样例值(解析后) 当前推断含义
0x00 3 char[3] 64 6f 7a "doz" 固定帧头 magic
0x03 4 u32 be 00 00 00 5a 90 帧总长度
0x07 4 u32 be 00 00 00 00 0 msg_id,当前抓包全为 0
0x0B 4 f32 be 43 88 a2 32 273.26715 pose[0],推断为 TCP X(mm)
0x0F 4 f32 be 43 f1 ed 7f 483.85544 pose[1],推断为 TCP Y(mm)
0x13 4 f32 be 43 e9 de 6b 467.73764 pose[2],推断为 TCP Z(mm)
0x17 4 f32 be c2 65 03 1e -57.253044 pose[3],推断为姿态角 W(deg)
0x1B 4 f32 be c2 b3 3c c3 -89.618675 pose[4],推断为姿态角 P(deg)
0x1F 4 f32 be c2 78 e0 15 -62.21883 pose[5],推断为姿态角 R(deg)
0x23 4 f32 be 3f 87 42 f5 1.0567309 joint_or_ext[0],推断为 J1(rad)
0x27 4 f32 be 3c 3f 12 8d 0.011662138 joint_or_ext[1],推断为 J2(rad)
0x2B 4 f32 be bc 92 95 29 -0.01789339 joint_or_ext[2],推断为 J3(rad)
0x2F 4 f32 be bc 78 61 d6 -0.015160045 joint_or_ext[3],推断为 J4(rad)
0x33 4 f32 be 3c b0 18 4c 0.02149596 joint_or_ext[4],推断为 J5(rad)
0x37 4 f32 be 3c 1c a1 a7 0.009560025 joint_or_ext[5],推断为 J6(rad)
0x3B 4 f32 be 00 00 00 00 0 joint_or_ext[6],扩展轴槽位,当前样本恒 0
0x3F 4 f32 be 00 00 00 00 0 joint_or_ext[7],扩展轴槽位,当前样本恒 0
0x43 4 f32 be 00 00 00 00 0 joint_or_ext[8],扩展轴槽位,当前样本恒 0
0x47 4 u32 be 00 00 00 02 2 tail[0],诊断状态字,物理语义未坐实
0x4B 4 u32 be 00 00 00 00 0 tail[1],诊断状态字,物理语义未坐实
0x4F 4 u32 be 00 00 00 00 0 tail[2],诊断状态字,物理语义未坐实
0x53 4 u32 be 00 00 00 01 1 tail[3],诊断状态字,物理语义未坐实
0x57 3 char[3] 7a 6f 64 "zod" 固定帧尾 magic

6. 已确认结论

6.1 已由真实抓包确认

  1. TCP 10010 是独立状态流,不是 TCP 10012 的请求/响应复用。
  2. 当前现场状态帧固定为 90B,不是早期静态分析里出现过的 134B
  3. msg_id20260428.pcap 当前全量样本中恒为 0
  4. tail[4]20260428.pcap 当前全量样本中恒为 (2, 0, 0, 1)
  5. pose[6] 的量纲表现符合 X/Y/Z(mm) + W/P/R(deg)
  6. joint_or_ext[6..8] 在当前现场样本中恒为 0

6.2 已由数值范围和交叉对照强支持

  1. joint_or_ext[0..5] 更像关节角 rad,而不是 deg
  2. 该判断与 ../analysis/UTTC_20260428_packet_validation.md 的结论一致。
  3. 该判断也与 UDP 60015 响应包中的关节 deg 形成互补关系:二者不能简单视作同单位直接复用。

7. 待确认项

以下内容当前不要写死为最终协议真义:

  1. tail[4] 四个 u32 分别代表什么控制器语义。
  2. msg_id 是否在其他控制柜版本、程序状态或异常态下会出现非零值。
  3. pose[3..5] 是否可以严格命名为 FANUC 标准 W/P/R,还是只是与其数值表现一致。
  4. joint_or_ext[6..8] 在带外部轴的现场是否仍复用同一布局。

8. 与当前代码实现的对齐情况

当前仓库里 Flyshot.Runtime.Fanuc 已按 90B 固定帧解析:

  • src/Flyshot.Runtime.Fanuc/Protocol/FanucStateProtocol.cs
  • tests/Flyshot.Core.Tests/FanucProtocolTests.cs

当前实现已经与抓包对齐的部分:

  1. 固定长度 90B
  2. doz ... zod 帧头帧尾校验
  3. pose[6] + joint_or_ext[9] + tail[4] 的字节布局
  4. tail[4] 原样保留到 ControllerStateSnapshot.StateTailWords

当前仍建议后续关注的点:

  1. FanucStateFrame 已把该字段从 JointDegrees 更正为 JointRadians,后续新增代码应继续沿用弧度制命名。
  2. 如果后续状态页或运行时逻辑需要直接展示该通道关节值,仍需明确标注这是 10010 的弧度值,避免和 UDP 60015 的 degree 语义混淆。

9. 建议用法

在当前 replacement 实现里,TCP 10010 更适合作为以下用途:

  1. 提供机器人当前笛卡尔位姿和关节反馈快照。
  2. 提供状态通道是否健康、是否陈旧的连接诊断依据。
  3. 保留 tail[4] 原始状态字,供现场排错或后续继续逆向。

当前不建议直接用 tail[4] 去驱动明确业务判断,除非后续拿到新的现场对照证据。