跳转至主要内容

06. 组合套装(Inverse3 + Wireless VerseGrip)

双设备教程:对准手柄并按住一个按键,即可将光标从Inverse3 向该方向移动。光标移动范围受球形工作空间的限制。

您将学到:

  • 从同一个状态帧中读取两种设备类型(inverse3 und wireless_verse_grip)
  • 根据手柄的位置确定其指向方向 四元数 (本地 +Y-轴)
  • 使用 set_cursor_position,将光标移动到一个计算得出的目标位置
  • 将目标点限制在安全工作球体内——Minverse 使用的半径比Inverse3
  • 设置一个 工作区预设 (arm_front_centered),以便原点位于射程的中间位置

流程​

  1. 两台设备均可识别:
    • C++- 启动时通过 HTTP 查询变体 GET /devices ab,随后会显示校准提示,并等待按下回车键。
    • Python从 WebSocket 的第一个状态帧中读取这两个设备 ID。
  2. 请注册该 会议简介 并在第一条消息中 configure.preset: arm_front_centered (一次性握手)。
  3. 每次月经周期:请阅读 orientation 指法和……的状态 buttons.{a, b}.
  4. 如果按住了一个移动键,请计算手柄在世界坐标系中的方向(R(q) · ĵ – 旋转后的单位轴(+Y),并将该值乘以 SPEED, 至目标位置。
  5. 请将目标点限定在工作空间球体内,并通过 set_cursor_position.
  6. (仅限 Python)根据以下内容调整球体半径: config.type 设备的—— minverse = 0.04 米,其余均为 0.10 米。

参数​

名称标准值Zweck
SPEED0.01 m/tick按住按键时的步进距离
RADIUS_INVERSE30.10 mInverse3 /Inverse3x 工作空间的边界半径
RADIUS_MINVERSE0.04 mMinverse 的工作区边界半径(仅限 Python——C++ 已固定为 0.10 编码)
PRINT_EVERY_MS200遥测数据限流
会话配置文件名称co.haply.inverse.tutorials:combined在Haply Hub中标记此模拟
启动前进行校准
  • 请让Inverse3 自行校准(或者将笔身放在Inkwell上,等待LED指示灯持续亮起)。
  • 请将墨水瓶的瓶盖取下。
  • 按住 A 或 B 键并转动摇杆——光标将朝摇杆指向的方向移动。

已读取的状态字段​

来自每个周期的状态框架:

  • data.inverse3[0].state.cursor_position — vec3
  • data.wireless_verse_grip[0].state.orientation — quaternion
  • data.wireless_verse_grip[0].state.buttons.{a, b, c} — Booleans
  • (Python,仅限第一个代码块) data.inverse3[0].config.type — 选择Inverse3 的半径,或Minverse
  • (Python,仅限第一个代码块) data.inverse3[0].status.calibrated — 当该值为 false 时,会提示用户

发送 / 接收​

根据四元数计算方向(旋转 +Y mit R(q)) 以及对球体的限制属于经典的线性代数——请参阅源文件。逆API部分包括握手过程以及每个周期发送的 set_cursor_position.

一个异步循环。Python 从第一个状态帧中读取两个设备 ID;握手过程取决于配置文件和 configure.preset: arm_front_centered 第一篇 set_cursor_position-呼吁。

async with websockets.connect(URI) as websocket:
while True:
msg = await websocket.recv()
data = json.loads(msg)

if first_message:
first_message = False
inverse3_id = data["inverse3"][0]["device_id"]
grip_id = data["wireless_verse_grip"][0]["device_id"]
radius = get_workspace_radius(data["inverse3"][0].get("config", {}))

# Handshake: profile + preset + first position command
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": inverse3_id,
"configure": {"preset": {"preset": "arm_front_centered"}},
"commands": {"set_cursor_position": {"position": position}},
}],
}
else:
# Per tick: update position from grip pointing direction (classic math, not shown), send
request_msg = {
"inverse3": [{
"device_id": inverse3_id,
"commands": {"set_cursor_position": {"position": position}},
}],
}

await websocket.send(json.dumps(request_msg))
包含在 SDK 安装程序中

教程 06 还会随 SDK 一起本地安装——请在 tutorials/06-haply-inverse-combined/ 位于该服务的安装目录中。

来源: Python·C++·C++ Glaze

另见: 控制命令 (set_cursor_position) · 类型 (四元数, vec3) · 剪辑与工作区(预设) · 教程 03(无线 VG) · 教程 05(位置控制)