18 网络传输 · TCP、UDP、ADB 与时间同步
为什么学这个(项目关联)
UMI 是三路异构数据流的融合系统:
- 相机流(板载/头显,图像到主机有传输延迟)
- 编码器流(ESP32 → USB 串口)
- 控制器位姿流(Quest → Wi-Fi UDP)
原文明确做了时延补偿:“把两组读数做时间对齐后,运动测试中标记与编码器读数匹配度最好;所有结果都做了该时延补偿。” 没有同步,融合数据就是错位的,训练数据直接污染。
知识点清单
1. 传输协议选型(原文的三方案对比)
| 方案 | 协议特点 | 适用 |
|---|---|---|
| TCP over ADB via USB | 可靠、有序、重传;经 ADB 隧道 | 成品系统(原文认为最适合最终产品) |
| TCP over ADB via Wi-Fi | 同上,无线 | 有可靠要求的无线场景 |
| UDP via Wi-Fi(原文选) | 无连接、不重传、不等待 | 实时调试:不因丢包阻塞,接口不受限 |
- TCP 三次握手、确认重传、队头阻塞(head-of-line blocking)
- UDP 尽力而为:丢一帧无所谓(下帧马上来),控制/追踪数据天然适合
- 关键思维:实时流要”新”,不要”全”;文件传输要”全”
2. ADB(Android Debug Bridge)
- Quest 是 Android 设备:
adb devices、adb install、adb forward端口转发、adb over Wi-Fi配对 - Unity 的 Build and Run 本质走 adb 装 APK
3. 多源时间同步(本节核心难点)
问题:三路流各有各的时钟与延迟——
- 相机:曝光时刻 ≠ 到达主机时刻(传输+解码延迟,几十~几百 ms)
- 串口:USB 缓冲
- UDP:网络抖动
策略:
- 源端打时间戳:数据包内带设备时钟时间(Quest 的 timestamp、ESP32 的 micros()),而非到达时间
- 时钟对齐:各设备时钟 ↔ 主机时钟的偏移估计(简单法:线性回归 offset 估计;进阶:PTP/NTP 思想、软件同步触发)
- 时延估计:互相关法——两路信号都包含同一运动(如快速开合夹爪),对时间序列做互相关找使相关度最大的 lag(原文做法即此类)
- 插值重采样:以最低频流(相机 ~30-60Hz)为主时钟,把高位姿流插值到相机时间戳
4. 数据 pipeline 工程实践
- 接收端架构:每路一个线程/协程 + 环形缓冲区(ring buffer),按时间戳归并
- 丢包容错:序列号检测,只告警不重传
- 落盘格式:分 episode 目录;rosbag 不必需(无 ROS 时用自定 zarr/npz/mp4)
- 后处理 pipeline 衔接 14 模仿学习 - ACT 与 Diffusion Policy 的数据格式
学习资源
| 资源 | 用途 |
|---|---|
| 《计算机网络:自顶向下方法》传输层章节 | TCP/UDP 原理 |
Python socket / asyncio 文档 | 收发实现 |
| ADB 官方文档 | Quest 调试 |
numpy 互相关 np.correlate / scipy.signal.correlate | 时延估计 |
实践任务
- 💻 Python 写 UDP 收发对:发送端 100Hz 推递增序列号,接收端统计丢包率与时延分布(直方图)
- 💻 同一 UDP 流改 TCP,对比在人为丢包(防火墙/断连 1s)下的行为差异(TCP 阻塞 vs UDP 丢弃)
- 💻 时延估计实验:同一事件(如快速开合夹爪)同时被相机与编码器记录,对两路信号互相关求 offset——复现原文”时延补偿”思想
- 💻 三流融合 demo:相机 30Hz + 模拟位姿 200Hz,按时间戳归并插值输出统一采样率的表
掌握标准(自测)
- 能画出本系统三路数据流的时间线图并标注各延迟来源
- 能写代码估计两路信号之间的时延并做补偿
- 能说清为什么 UDP 适合实时追踪、TCP 适合最终产品
- 理解”源端时间戳 > 到达时间戳”的原因
关联笔记
- 上游:17 位姿追踪 - Unity 与 Meta Quest 开发、16 嵌入式 - AS5600 编码器与 XIAO ESP32C6
- 下游:14 模仿学习 - ACT 与 Diffusion Policy(数据格式)、31 复刻路线图与里程碑 M4
- 原文对应章节:01 - 原文存档 - Dream-UMI 开发手记 “Quest应用程序”传输链路部分 + “相机时延”
实践记录
(学习时在这里追加:日期 / 做了什么 / 踩坑 / 疑问)