跳转至主要内容

07. 基座与安装:试验场地

以交互方式控制 剪辑转换 设备的,并展示了如何 configure.basis, configure.preset et configure.mount 在协议层面上协同工作。保持水平基面固定,以确保交互式焦点始终位于配置控件上。

您将学到:

  • 定义一个 基本排列 ("XZY" → 应用基准点(Y轴向上))
  • 选择一个 预设 (arm_front) 并理解其配置内容
  • 将运行时的拼接替换为旋转四元数(通过键盘控制)
  • 互斥规则: mount et preset 不能在同一个区块中并存 设备配置
  • 《……的点状语义学》 configure : 每次按键都会发送恰好一条配置消息
  • (C++ Glaze) 使用……对互斥字段进行建模 std::optional

工作流程​

  1. 收到第一条消息时:发送该消息 会话配置文件, configure.basis: "XZY" et configure.preset: arm_front. 开始发送 set_cursor_force 适用于固定地面。
  2. 每个循环中:读取光标的Y值,计算 force_y = max(0, (floor_pos - y) * stiffness) 然后发送出去。
  3. 当用户按下蒙太奇旋转键时,请设置 pending_configure = true.
  4. 在下一个循环中:构建一个块 configure.mount 通过一种变换,其中 rotation 是一个单位四元数(由当前俯仰角和偏航角依次与Z、X相乘得到)。省略 preset — 在协议层面,这两者是相互排斥的。
  5. 重置按钮(R) 会清除替换操作;以下配置相当于 preset.

参数​

Nom缺陷角色
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 et preset 彼此互斥

该服务拒绝了一个 设备配置 其中包含这两者。一旦用户替换了该组件,教程就省略了 preset 以下每种配置。按下 R 反应性 preset 在进行以下配置时,请移除 mount.

不同的输入模式

C++ 版本会通过后台的 stdin 线程逐行读取用户输入(输入每个字母后请按回车键)。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

另请参阅: 基本排列 · 剪辑与工作区 · 设备配置 · 控制命令(set_cursor_force) · 类型(转换) · 教程 04(Hello Floor)