跳至主要内容
版本:3.5.x

05. 位置控制

通过以下方式将Inverse3 移动到目标位置 set_cursor_position. 交互模型因语言而异 — C++ 使用一次性随机目标,Python 使用基于键盘的连续移动。

您将学到:

  • 使用 set_cursor_position 用于位置模式控制
  • 同一底层命令的两种不同交互模型
  • 将目标固定到工作空间球体上——Minverse 半径比Inverse3更小
  • 设置工作区预设,使原点位于工作区中心

工作流程

C++(随机目标模型)

  1. 启动一个后台输入线程,用于读取行缓冲的按键输入(n, +, -, q) 从标准输入读取。
  2. 打开 WebSocket。在第一个状态帧中,注册 会话配置文件 并设置 configure.preset: arm_front_centered. 在一个球体内部生成第一个随机目标(拒绝采样,半径 0.08 米)。
  3. 每次 tick,发送一个 set_cursor_position 命令发送到当前目标。光标会平滑地跟随它——该服务会进行速率限制和插值。
  4. 当用户输入 n + 按下 ENTER 键,输入线程将生成一个新的随机目标。 + / - 调整速度; q 退出。

Python(按住移动模式)

  1. 打开 WebSocket。在第一个状态帧中,检查 status.calibrated — 如果设备尚未校准,则提示用户。
  2. 阅读 config.type 选择工作区半径(minverse = 0.04 米,其余情况 = 0.10 米)。
  3. 注册 会话配置文件 并设置 configure.preset: arm_front_centered.
  4. 每次迭代:检测键盘状态(W/A/S/D/Q/E),通过以下方式更新目标位置: SPEED 沿着每个按下的轴,将其固定到工作区球体上,并发送 set_cursor_position. R 将目标重置为原点。

参数

名称默认 (C++)默认 (Python)目的
workspace_radius / RADIUS_INVERSE30.08 m0.10 m (Inverse3) / 0.04 m (Minverse)目标球体半径
speed_step / SPEED0.01 / 新闻0.00005 m / tick每次交互的步骤
PRINT_EVERY_MS100遥测节流阀(Python)
会话配置文件co.haply.inverse.tutorials:position-control同上在Haply 中识别
校准检查(Python)

Python 变体检查 status.calibrated 从第一个状态帧开始,如果设备尚未校准,则会提示用户。C++ 版本则假设校准已完成。

读取状态字段

  • data.inverse3[0].device_id — 用于构建该命令
  • data.inverse3[0].state.cursor_position — 遥测
  • (Python,仅限第一帧) data.inverse3[0].config.type — 选择Inverse3 Minverse
  • (Python,仅限第一帧) data.inverse3[0].status.calibrated — 如果为 false,则提示用户

发送/接收

沟通流程

  • C++ 运行一个后台标准输入线程,该线程负责写入 std::atomic<float> 目标;WebSocket 线程会在每个时间步长读取这些数据。在 n + 按下 ENTER 键,输入线程会生成一个新的随机目标;在 q,这两个帖子都被关闭了。
  • Python 这是单线程异步操作——WebSocket 循环会在每个 tick 周期轮询键盘状态并进行更新 position 直接。

Inverse-API 的有效载荷是相同的:第一个数据包携带会话配置文件 + configure.preset,后续的滴答声仅包含 set_cursor_position.

单线程异步循环。键盘轮询(handle_keys) 在每个时钟周期内内联执行——不使用线程。 config.typestatus.calibrated 从第一个状态帧中读取一次。

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

if first_message:
first_message = False
device_id = data["inverse3"][0]["device_id"]
radius = get_workspace_radius(data["inverse3"][0].get("config", {}))
# Handshake: profile + preset (one-shot)
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": device_id,
"configure": {"preset": {"preset": "arm_front_centered"}},
}],
}
else:
# Per tick: update position from keyboard (classic polling, not shown), send command
position = handle_keys(position, radius)
request_msg = {
"inverse3": [{
"device_id": device_id,
"commands": {"set_cursor_position": {"position": position}},
}],
}

await websocket.send(json.dumps(request_msg))

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

相关: 控制命令 (set_cursor_position) · 安装与工作区(预设) · 类型 (vec3) · 教程 06(综合)