传感器及外围设备
Meta Quest 3 VR Teleop 规格
完整的技术参考:UDP 数据包架构、字段类型和字节布局、端到端延迟细分、关键可调参数以及兼容的 Arm 规范。
系统概述
硬件和运行时
| 耳机 | Meta Quest 3(需要手动追踪模式) |
| 统一版本 | 2022.3 LTS 或更高版本 · XR Hands 包 · OpenXR 插件 |
| 主机运行时 | Python 3.10+(Linux 或 macOS;无需 ROS) |
| 网络要求 | 同一 LAN 子网; 推荐的 Wi-Fi 6 接入点 |
| 右侧 UDP 端口 | 8888 |
| 左侧 UDP 端口 | 8889(仅限双边控制;否则未使用) |
| 数据包速率(发送方) | 来自 Unity 的 ~50 Hz(Unity 的固定更新循环) |
| 机器人指令率 | 默认 30 Hz(可通过 CONTROL_HZ 配置) |
| 主要 SDK (Piper) | Piper_sdk · python-can · CAN over USB 适配器 |
UDP 数据包架构
每个数据包都是固定长度的 45 字节二进制消息。 所有多字节字段都使用 小尾数法 字节顺序。 为了向前兼容,接收器将忽略末尾附加的未知字节。
二进制数据包布局 — 总共 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% 开始,仅在运动得到充分验证后才提高。
关键可调参数
统一检查器(VRHandPoseSender)
| 位置偏移 (m) | (0, 0, 0.3) - Piper 起点 |
| 旋转偏移(度) | (0, 90, 0) - Piper 起点 |
| 比例因子 | 0.75 — 将手部运动缩放到 Piper 工作空间 |
| 工作空间X夹(mm) | ±400(派珀); ±600(xArm6) |
| 工作空间 Z 夹具 (mm) | 50 – 700(派珀); 0 – 900 (xArm6) |
| UDP目标端口 | 8888(右手)/8889(左手) |
Python 服务器(teleoperation_main.py)
| CONTROL_HZ | 30 Hz——机器人指令率; 与伺服速率匹配 |
| QUEUE_MAXSIZE | 3 — 在接收器和控制器线程之间缓冲的帧 |
Piper_controller.py(AgileX Piper)
| SPEED_PERCENT | 25%——最大关节速度分数; 逐渐提高 |
| X_最小 / X_最大 (毫米) | −400 / +400 |
| Y_最小/Y_最大(毫米) | −400 / +400 |
| Z_最小/Z_最大(毫米) | 50 / 700 |
| GRIPPER_MAX_UM (微米) | 70 000 — 70 mm 物理开口 |
| SDK位置单位 | 微米(整数)— 将毫米值乘以 1 000 |
| SDK定向单元 | 毫度(整数)— 将度值乘以 1 000 |
| CAN接口 | can0 (默认) — 在运行之前使用 can_activate.sh 激活 |
SVRC 的兼容武器
| 手臂 | DOF | SDK/接口 | 控制器文件 | 地位 |
|---|---|---|---|---|
| AgileX 派珀 | 6 | Piper_sdk · CAN over USB | piper_controller.py | 生产就绪 |
| 开臂 | 7 | SocketCAN / ROS 2 MoveIt2 | openarm_controller.py | 贝塔 |
| DK1 双手套件 | 双6 | 同时端口 8888 + 8889 | dk1_controller.py | 贝塔 |
| VLAI L1 | 双6 | ROS 2 桥接器·TCP/IP | vlai_l1_controller.py | 开发中 |
软件要求
任务 3/团结方
| 统一 | 2022.3 LTS 或更高版本 |
| XR手包 | com.unity.xr.hands ≥ 1.3 |
| OpenXR 插件 | com.unity.xr.openxr ≥ 1.9 |
| 原始XR SDK | 可选,但建议用于直通 |
| 手部追踪模式 | 在 Quest 系统设置中启用(移动追踪) |
控制PC端/Python端
| Python | 3.10 或更高版本(使用联合类型语法) |
| Sect_sdk | pip install piper_sdk |
| 蟒蛇可以 | pip install python-can |
| CAN接口 | USB 转 CAN 适配器; 激活与 can_activate.sh can0 1000000 |
| 仅标准库 | 套接字、结构、队列、线程、信号、时间 |