跳转至正文

07. Basis & Mount 游乐场

设备的 安装座转换以交互方式控制, configure.basis, configure.preset, configure.mount展示了它们在 Wire 协议层面上是如何协同工作的。通过保持固定的水平底线,确保交互式焦点始终停留在 configure 命令上。

学习内容:

  • 基序排列 设置 ("XZY" → Y轴向上方向(应用程序坐标系))
  • 预设(arm_front) 选择并理解该预设包含的内容
  • 使用旋转四元数在运行时重写按键映射(基于键盘输入)
  • 互斥规则: mount哇 preset像……一样 设备配置 不能同时存在于同一个区块中
  • 一次性 configure 操作:每次按下按键时,都会发送一次“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. 在下一个时点 rotation包含该单位四元数(当前俯仰角/偏航角的Z-then-X合成)的变换 configure.mount 构成块。 preset此处省略。这两个字段在电线上是互斥的。
  5. 重置键(R) 会取消覆盖。在接下来的 configure 步骤中,将再次 preset使用。

参数​

姓名默认值用途
BASIS"XZY"轴排列— Y轴向上方向的应用坐标系
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结束
mount哇 preset它们是相互排斥的

该服务包含这两个字段 设备配置 拒绝该块。如果用户重定义了挂载,则本教程在后续的所有 configure 步骤中 preset省略。 R点击后,在接下来的配置中 preset这又被重新使用, mount不包括在内。

输入模型的差异

C++ 版本在后台的 stdin 线程中读取按行输入(每次输入一个字符后按 ENTER 键)。Python 则在主异步循环中 keyboard 由于该软件包会轮询实时键盘输入,因此无需按 ENTER 键。键位与命令对应。

“正在阅读”字段​

data.inverse3[i].state读取的值:

  • cursor_position.y — vec3. 用于计算地板穿透量。
  • 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))
随SDK安装程序一起提供

教程 07 会随 SDK 一起安装到本地。在服务安装目录下的 tutorials/07-haply-inverse-basis-and-mount/可在……中找到。

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

相关条目: 基序排列 · Mount & Workspace · 设备配置 · 控制命令 (set_cursor_force) · 类型 (transform) · 教程 04(Hello Floor)