Skip to content

fix(transport): 丢弃从爪撞车重发的重复数据帧 - #31

Merged
Vertax42 merged 1 commit into
mainfrom
main-0.4.5-dedupe-resent-data-frames
Nov 12, 2026
Merged

Vertax42 merged 1 commit into
mainfrom
main-0.4.5-dedupe-resent-data-frames

Conversation

@xensexyq

@xensexyq xensexyq commented Nov 6, 2026 •

Copy link
Copy Markdown
Collaborator

背景

从爪固件 1.2.17 在上行帧与主机下行重叠时,会把同一帧原样重发(序号、命令、内容都相同),这是为旧硬件准备的补救措施。去掉控制串口的下拉电阻后,重叠不再损坏原帧,主机会收到两份完整的帧,而传输层把两份都交付了出去:

  • 全双工主动上报 + ForcePositionController 实测(从爪 01s,600 s,目标下发 + 97 Hz 查询):电机状态 106.7 Hz,MCU 统计的目标更新也是 106.7 Hz。每份重复的状态帧都让控制器多走一步、多发一个目标。
  • 一次按键(0x15)也会被上报两次。

改动

  • Transport::dispatch_:从线上读到的 DATA 帧,如果与上一个线上 DATA 帧的序号、命令、地址、内容完全相同,就丢弃,并计入新增的 TransportStats.duplicate_data_dropped(Python 同名字段)。
  • 不会误删正常帧的依据:固件主动发出的每一帧都取同一个 8 位计数器的下一个值(protocol_get_next_seq,原版 a7dc07f 也是如此);重发在固件发送锁内紧跟原帧之后。
  • 交换模式不受影响:交换应答里的记录经 inject_data() 交付,不经过这条路径。这些记录共用应答的序号,也从不参与比较。
  • 主爪固件、以及 1.2.17 之前的从爪固件都不会重发,因此不会触发去重。
  • 测试替身 fake_follower / fake_leader 改为像固件一样递增数据帧序号。原先序号恒为 0,夹爪静止时相邻状态帧逐字节相同,加入去重后有 8 项控制器测试失败;恢复旧替身并关掉去重后,这 8 项全部通过,说明是替身与真实固件不符。

测试

  • 新增 4 项传输层测试:逐字节重复的帧被丢弃;序号、命令或内容任一不同的帧都会交付;中间夹一个 ACK 不影响识别重发;注入的交换记录从不去重。
  • 变异检验:去掉去重、不比较内容、不比较序号、不比较命令、对注入路径也去重,五种改法均被测试检出。
  • C++ 550 项、Python 155 项全部通过。
  • 实机(从爪 01s 已拆下拉电阻,固件 1.2.17,全双工主动上报,夹爪往复运动,97 Hz 查询,600 s):
指标 修改前(682eda6) 本分支
电机状态 106.7 Hz 100.0 Hz
MCU 目标更新 106.7 Hz 100.0 Hz
主机坏字节 / CRC / IMU 缺样 / 序号缺口 0 0
固件重发 — 5985(重复数据帧 3830 + 重复 ACK 2155,与原始字节离线核对一致)
duplicate_data_dropped — 3830
  • 实机(从爪 0094s 未拆下拉电阻,固件 1.2.17,同样条件 600 s,3 路相机):主机坏字节 180 807(3947 段,原帧被撞坏),固件重发 3990、重发用尽 0;duplicate_data_dropped 40(只在原帧碰巧完好时触发);完整帧序号缺口 0、IMU 缺样 0;电机状态 / IMU / MCU 目标更新均为 100.0 Hz。去重在旧硬件上不会误删重发补回的帧(原始字节离线核对:坏段 3947 + 重复数据帧 40 + 重复 ACK 14,与固件重发数一致)。

  • 实机(从爪 01s,固件 1.2.17,分时交换模式,往复运动,300 s):交换 60000 次(遥测 30000 + 目标 30000),超时 / NACK / 格式错误 / 目标拒绝 / IMU 队列溢出均为 0;MCU 目标更新 30000 = 主机下发 30000;固件撞车 0;duplicate_data_dropped 0、原始重复数据帧 0;电机状态 100.0 Hz、IMU 100.04 Hz,缺样 0;判定 PASS。交换模式行为不变。

待办(草稿)

  • 未拆电阻的从爪(0094s)用本分支跑全双工
  • 分时交换模式实机短测,确认行为不变
  • 固件文档 TX_COLLISION_RETRY.md 里“电机状态重复一帧无副作用”的表述已更正:XenseRobotics-AI/tc-gu-01#25

🤖 Generated with Claude Code

从爪固件 1.2.17 在上行与主机下行重叠时原样重发同一帧(序号、命令、
内容都相同)。在去掉串口下拉电阻的硬件上重叠不再损坏原帧,两份都到达,
传输层原样交付两份:全双工主动上报 + ForcePositionController 实测
(从爪 01s,600 s,目标 + 97 Hz 查询)电机状态与 MCU 目标更新均为
106.7 Hz,每份重复状态都让控制器多下发一次目标。

- 从线上读到的 DATA 帧若与上一个线上 DATA 帧的序号、命令、地址、内容
  完全相同则丢弃,计入 TransportStats.duplicate_data_dropped(含 Python)
- 固件主动发出的每帧取同一个 8 位计数器的下一个值,重发在发送锁内紧跟
  原帧,正常帧不会命中
- 交换模式记录经 inject_data() 交付、共用应答序号,不参与比较,不受影响;
  主爪固件与 1.2.17 之前的从爪固件不重发,不会触发
- 测试替身改为像固件一样递增数据帧序号(原先恒为 0,静止时相邻状态帧
  逐字节相同,去重后 8 项控制器测试失败;恢复旧替身并旁路去重即全部通过)
- 新增 4 项传输层测试;去掉去重、不比较内容/序号/命令、注入路径也去重
  五种变异均被检出;C++ 550 项、Python 155 项通过

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Vertax42

Copy link
Copy Markdown
Collaborator

在 TCGU01A45A0016s(已拆下拉电阻,固件 1.2.17)上复测:

  • 静态,推送 100 Hz + 97 Hz 查询,120 s:main 0.4.5 状态 102.34 Hz;本分支 100.00 Hz,duplicate_data_dropped 267,撞坏字节 0。
  • 运动,ForcePositionController 20%↔80% 往返 785 次 + 20 Hz 查询 + 腕相机与两路触觉,600 s:状态 100.00 Hz,最大间隔 10.9 ms,撞坏字节 / CRC / ACK 超时 / 队列丢弃 0,MCU 控制环 500 Hz 0 错误。
  • TCGU01A28Z0089s(未拆电阻)120 s:duplicate_data_dropped 5,状态 100.00 Hz,无误删。

可以合并。

🤖 Generated with Claude Code

@Vertax42
Vertax42 marked this pull request as ready for review November 12, 2026 08:17
@Vertax42
Vertax42 merged commit 8ec56fa into main Nov 12, 2026
3 checks passed
@Vertax42
Vertax42 deleted the main-0.4.5-dedupe-resent-data-frames branch November 12, 2026 08:18
Vertax42 added a commit that referenced this pull request Nov 12, 2026
Drop the follower's verbatim collision resend in pushed streaming (#31):
on a follower with the control-UART pull-down removed both copies arrive,
and each duplicate motor status stepped the controller once more. Verified
on TCGU01A45A0016s (pull-down removed): 102.34 -> 100.00 Hz static, and a
600 s push-mode soak with motion, 20 Hz queries and all cameras at 100.00 Hz
with no corrupted bytes. Bundled firmware unchanged (1.2.7 / 1.2.17).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants