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

07. Basis & Mount 游乐场

以交互方式驱动设备的 挂载转换 并演示了如何 configure.basis, configure.presetconfigure.mount 在终端中协同工作。保持固定的水平界面,以便交互重点始终集中在配置命令上。

您将学到:

  • 设置一个 基底置换 ("XZY" → Y-up 应用框架)
  • 选择一个 预设 (arm_front) 并了解其配置内容
  • 在运行时使用旋转四元数覆盖坐骑(键盘控制)
  • 互斥规则: mountpreset 无法共存于同一 设备配置
  • 单篇 configure 语义:每次按键都会发送且仅发送一条配置消息
  • (C++ Glaze) 使用 std::optional

工作流程

  1. 在第一条消息中:发送 会话配置文件, configure.basis: "XZY"configure.preset: arm_front. 开始发送 set_cursor_force 用于固定地板。
  2. 每次 tick:读取光标 Y 坐标,计算 force_y = max(0, (floor_pos - y) * stiffness),发送。
  3. 当用户按下某个旋转键时,标记 pending_configure = true.
  4. 在下一个时钟周期:构建一个 configure.mount 具有以下变换的块 rotation 是一个单位四元数(当前俯仰角与偏航角的Z-X组合)。省略 preset — 这两者在网络上是互斥的。
  5. 重置键 (R) 清除覆盖设置;下次配置将回退到 preset 再次。

参数

名称默认目的
BASIS"XZY"轴置换— Y-up 应用框架
DEVICE_PRESET / DEVICE_CONFIG_PRESET"arm_front"命名预设— 原点位于设备底座
FLOOR_POS_Y0.0 m固定地板平面(应用-Y)
STIFFNESS1000 不适用地板弹簧刚度
MOUNT_STEP_DEG10°每次按键的旋转角度
PRINT_EVERY_MS200遥测节流阀

控制

关键行动
W / S沿设备+X轴旋转支架±10°(俯仰角)
A / D将支架沿设备+Z轴旋转±10°(偏航)
R重置挂载 — 恢复为预设
H显示控件
Q退出
mountpreset 互斥

该服务拒绝了一个 设备配置 包含两者的代码块。一旦用户覆盖了挂载操作,本教程便省略了 preset 从后续的每次配置开始。按下 R 重新启用 preset 在接下来的配置和删除操作中 mount.

不同的输入模型

C++ 变体在后台的 stdin 线程上读取按行输入(每个字母输入后按 ENTER 键)。Python 使用 keyboard 用于在主异步循环中进行实时按键轮询的包——无需按下 ENTER 键。支持相同的按键和命令。

读取状态字段

来自 data.inverse3[i].state:

  • cursor_position.yvec3,用于计算楼板穿透深度
  • current_cursor_force — 用于遥测报告

发送/接收

各变体的有效载荷形状相同;有趣的区别在于它们各自如何构建互斥的 mount / preset 分支机制以及输入线程如何向 WebSocket 线程发送信号。

通过...实现的单线程异步循环,并进行实时键位轮询 keyboard 包。 pending_configure 这是一个由键处理程序设置的全局标志,并在每次 configure 数据块已发送。

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"]
# Handshake: profile + basis + preset
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": device_id,
"configure": build_configure_block(first_handshake=True),
# -> {"basis": {"permutation": "XZY"},
# "preset": {"preset": "arm_front"}}
}],
}
else:
handle_key_inputs() # may set pending_configure = True (classic, not shown)

y = data["inverse3"][0]["state"]["cursor_position"]["y"]
force_y = 0.0 if y > FLOOR_POS_Y else (FLOOR_POS_Y - y) * STIFFNESS

entry = {
"device_id": device_id,
"commands": {"set_cursor_force":
{"vector": {"x": 0.0, "y": force_y, "z": 0.0}}},
}
if pending_configure:
entry["configure"] = build_configure_block(first_handshake=False)
# -> {"mount": {...}} OR {"preset": {...}} (never both)
pending_configure = False

request_msg = {"inverse3": [entry]}

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

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

相关: 基底置换 · 安装与工作区 · 设备配置 · 控制命令 (set_cursor_force) · 类型(转换) · 教程 04(Hello Floor)