UDP 数据包架构
每个数据包都是固定长度的 45 字节二进制消息。 所有多字节字段都使用 小尾数法 字节顺序。 为了向前兼容,接收器将忽略末尾附加的未知字节。
| 场地 |
类型 |
字节 |
描述 |
| 标头 |
uint8[4] |
4 |
魔法字节 0x52 0x43 0x54 0x50 — ASCII“RCTP”。 具有错误魔法值的数据包将被默默丢弃。 |
| 时间戳 |
浮动64 |
8 |
统一 Time.realtimeSinceStartup 几秒钟内。 用于抖动测量; 不由机器人控制器解释。 |
| 位置x |
浮动32 |
4 |
末端执行器 X 位置(以米为单位),VR 世界框架(右手,Y 向上)。 转换为 mm 机器人框架 transform_position(). |
| 铭文 |
浮动32 |
4 |
VR 世界框架中末端执行器 Y 位置(以米为单位)。 |
| 位置z |
浮动32 |
4 |
末端执行器 Z 位置(以米为单位),VR 世界框架。 |
| rot_x、rot_y、rot_z、rot_w |
浮点32×4 |
16 |
VR 世界框架中末端执行器旋转作为单位四元数。 转换为欧拉(横滚/俯仰/偏航): quat_to_euler() 在传递给机器人 SDK 之前。 |
| 夹子 |
浮动32 |
4 |
夹具开度: 0.0 =完全关闭, 1.0 =完全打开。 源自捏力 VRGripperController.cs. |
| 旗帜 |
uint8 |
1 |
位 0:跟踪有效(1 = 检测到手)。 位 1:请求紧急停止(1 = 操作员按下菜单)。 保留剩余位。 |
字节偏移摘要:标头 0–3、时间戳 4–11、pos_x 12–15、pos_y 16–19、pos_z 20–23、rot_x 24–27、rot_y 28–31、rot_z 32–35、rot_w 36–39、夹具 40–43、标志 44。
Python struct 解包格式字符串:
进口 struct
PACKET_MAGIC = b'\x52\x43\x54\x50' # "RCTP"
PACKET_FMT = '<4sdffffffffb B'
# ^ ^ ^^^^^^^^^^ ^ ^
# | | pos xyz | flags (uint8)
# | timestamp gripper (float32)
# header (4 bytes) rot xyzw (float32×4)
定义 解析数据包(data: bytes) -> dict | None:
如果 len(data) < struct.calcsize(PACKET_FMT):
返回 None
fields = struct.unpack_from(PACKET_FMT, data)
header, ts, px, py, pz, rx, ry, rz, rw, gripper, flags = fields
如果 header != PACKET_MAGIC:
返回 None
返回 {
“时间戳”: ts,
“位置”: (px, py, pz),
“旋转”: (rx, ry, rz, rw),
“抓手”: gripper,
“有效的”: bool(flags & 0x01),
“停止”: bool(flags & 0x02),
}
端到端延迟
使用 AgileX Piper 臂在 Wi-Fi 6 LAN 上以 30 Hz 控制速率和 25% 速度限制进行测量。 数值具有典型性; 实际延迟取决于 Wi-Fi 条件和机器人伺服速率。
~20 毫秒
Quest 3 追踪管道
手部姿势传感器融合到 Unity 回调
<5毫秒
UDP 传输
Wi-Fi 6 局域网; 在较旧的 Wi-Fi 上最多约 15 毫秒
<2毫秒
Python 解析和队列
结构解包+队列插入
30–80 毫秒
机器人轨迹执行
取决于速度限制和移动距离
| Wi-Fi 6 LAN,速度 25% |
50–120 毫秒 |
| Wi-Fi 5 LAN,速度 25% |
80–150 毫秒 |
| 软件急停响应(位 1 路径) |
1 个控制周期(30 Hz 时约 33 ms) |
| 跟踪丢失检测 |
立即(当前数据包中的标志字节) |
保持速度限制保守以减少延迟感。
主要的感知延迟部分是机器人轨迹执行。 较低的 SPEED_PERCENT 即使实际往返时间相似,也使系统感觉更具可预测性。 从 25% 开始,仅在运动得到充分验证后才提高。