UDP接收-EMF位姿
本文档说明 HumanHand 通过 UDP 发送的 EMF 传感器位姿 与 磁发射源 IMU 协议,供接收端对接。
1. 功能概述
| 项目 | 说明 |
|---|---|
| 输出内容 | 五指 EMF 位姿 + 可选小臂位姿 + 磁发射源 IMU |
| 传输协议 | UDP 单播,无握手 |
| 输出频率 | 默认 120 Hz |
| 协议标识 | FNIM,版本 2 |
| 单包大小 | 240 字节(固定) |
| 手别 | 每包一只手;双手时左右各发一包 |
软件路径:用户设置 → 数据发送 → 输出格式:线圈位姿+IMU(FNIM v2)。
2. 发送配置
| 参数 | 默认值 | 说明 |
|---|---|---|
| 目标 IP | 127.0.0.1 | 可在「数据发送」中修改 |
| 目标端口 | 15001 | 可在「数据发送」中修改 |
| 字节序 | 小端(Little-Endian) | 所有多字节字段 |
3. 坐标系说明
EMF 传感器位姿与磁发射源 IMU 均表达在该手的局部坐标系下。
3.1 EMF 传感器位姿(相对本手套磁发射源)
| 项目 | 说明 |
|---|---|
| 原点 | 本手套磁发射源 |
| 轴向 | RFU(右-前-上) |
| 位置单位 | 毫米(mm) |
| 旋转 | 四元数 w, x, y, z |
RFU(右-前-上)轴向定义(手局部):
| 轴 | 含义 |
|---|---|
| X | 右(左手小拇指指向大拇指方向,右手大拇指指向小拇指方向) |
| Y | 前(指尖方向) |
| Z | 上(手心指向手背方向) |
左右手均相对各自手套上的磁发射源;双手各自使用上述 RFU 手局部轴。
3.2 磁发射源 IMU
| 字段 | 单位 | 轴向 |
|---|---|---|
| accel_mps2 | m/s² | RFU(右-前-上),定义同 §3.1 轴表 |
| gyro_radps | rad/s | RFU(右-前-上),定义同 §3.1 轴表 |
未收到发射源 IMU 时,上述字段为 0。
4. 传感器索引
每包 6 个槽位(每槽 32 字节):
| 索引 | 名称 | 说明 |
|---|---|---|
| 0 | thumb | 拇指 |
| 1 | index | 食指 |
| 2 | middle | 中指 |
| 3 | ring | 无名指 |
| 4 | pinky | 小指 |
| 5 | forearm | 小臂(可选;未接或未标定时 valid=0) |
5. 数据包结构
5.1 整体布局
text
偏移 0 : 包头(24 字节)
偏移 24 : 6 个传感器槽(192 字节)
偏移 216 : 磁发射源 IMU(24 字节)
合计 : 240 字节5.2 包头(24 字节)
| 偏移 | 大小 | 类型 | 字段 | 说明 |
|---|---|---|---|---|
| 0 | 4 | uint32 | magic | 0x464E494D("FNIM") |
| 4 | 1 | uint8 | version | 2 |
| 5 | 1 | uint8 | flags | 1=左,2=右,0=无效 |
| 6 | 2 | uint16 | reserved | 0 |
| 8 | 4 | uint32 | frame_number | 帧序号 |
| 12 | 8 | uint64 | timestamp_ns | 主机单调时钟纳秒 |
| 20 | 4 | uint32 | quat_order | 0x77787A79(表示 wxyz) |
5.3 flags
| 值 | 含义 |
|---|---|
| 0 | 无效,丢弃 |
| 1 | 左手 |
| 2 | 右手 |
5.4 单槽(32 字节,i = 0..5)
| 相对偏移 | 字段 | 类型 | 说明 |
|---|---|---|---|
| 0 | position_mm.x/y/z | float32×3 | 毫米 |
| 12 | quaternion.w/x/y/z | float32×4 | wxyz |
| 28 | valid | uint8 | 1=有效 |
| 29 | reserved | uint8[3] | 0 |
仅当 valid == 1 时使用该槽位姿。
5.5 磁发射源 IMU(24 字节)
| 相对偏移 | 字段 | 类型 | 单位 |
|---|---|---|---|
| 0 | accel_mps2.x/y/z | float32×3 | m/s² |
| 12 | gyro_radps.x/y/z | float32×3 | rad/s |
6. 时间戳与帧序号
| 字段 | 含义 |
|---|---|
| timestamp_ns | 单调时钟纳秒,适合测间隔与抖动 |
| frame_number | 丢包 / 乱序检测 |
默认 120 Hz 时包间隔约 8.33 ms。
7. 双手模式
- 左手包:
flags = 1 - 右手包:
flags = 2
同一时刻可能连续收到两包,按 flags 分别处理。
8. 接收端检查清单
- 长度 == 240
magic == 0x464E494D且version == 2quat_order == 0x77787A79flags为 1 或 2- 仅使用
valid == 1的槽 - 使用包尾发射源 IMU;无有效 IMU 时可为全 0
9. C 结构体参考
c
#pragma pack(push, 1)
#define FNIM_MAGIC 0x464E494Du
#define FNIM_VERSION 2u
#define FNIM_PKT_SIZE 240u
#define FNIM_SLOTS 6u /* 0..4 五指, 5 小臂 */
typedef struct {
float px, py, pz; /* mm */
float qw, qx, qy, qz; /* wxyz */
uint8_t valid;
uint8_t reserved[3];
} FnimSlot;
typedef struct {
uint32_t magic;
uint8_t version;
uint8_t flags;
uint16_t reserved;
uint32_t frame_number;
uint64_t timestamp_ns;
uint32_t quat_order;
} FnimHeader;
typedef struct {
FnimHeader header;
FnimSlot slots[FNIM_SLOTS];
float accel_mps2[3]; /* 发射源 IMU */
float gyro_radps[3];
} FnimPacket;
#pragma pack(pop)10. 参考实现
站点提供 udp_receiver.py,与关节同一脚本、同一默认端口 15001。上位机选「线圈位姿+IMU」后即可看到 6 路线圈(毫米)和发射源 IMU。
关节位姿协议见UDP接收-关节位姿。
11. 与「关节位姿」对比
| 对比项 | EMF + 发射源 IMU | 关节位姿(FSNH) |
|---|---|---|
| 魔数 | FNIM 版本 2 | FSNH 版本 4 |
| 包长 | 240 B | 612 B(腕)/ 640 B(小臂) |
| 内容 | 6 槽位姿 + 发射源 IMU | 21 或 22 关节/手 |
| 位置单位 | 毫米 | 米 |
| 坐标系 | 磁源跟踪系 | 腕相对(默认左 RFU / 右 LBU) |
| 双手 | 左右各一包 | 左右各一包 |
| 时间戳 | 单调时钟纳秒 | 单调时钟纳秒 |
