跳至主要内容

01. 打印Inverse3

连接到仿真 WebSocket,并持续接收服务报告的第一个Inverse3 的光标位置、速度和力数据。

您将学到:

  • 建立 WebSocket 连接并接收初始的完整状态消息
  • 发送零力的 set_cursor_force 保活指令,使会话持续运行
  • 注册会话配置文件,以便Haply Hub 识别您的仿真
  • 仅在第一条消息中进行握手的方式——首次发送后移除 session/configure
  • 按部分更新语义读取工作空间的 transform(位置、旋转、缩放)
  • 将控制台输出限制在可读的频率

工作流程​

  1. 跳转至 ws://localhost:10001 的 WebSocket。服务会立即推送一个完整状态帧,其中列出了已连接的设备。
  2. 在收到第一帧时,选取第一个Inverse3 的 device_id,并构建包含两部分的请求消息:
    • session.configure.profile.name —— 向Haply Hub注册该仿真。
    • 针对每台设备的 set_cursor_force 指令,力向量为零。服务将其用作心跳信号——只要持续收到指令,服务就会持续发送状态帧。
  3. 将消息发回去。在下一个周期开始前移除 session 字段——会话配置文件仅用于初次握手;后续周期仅发送指令。
  4. 对于随后的每一帧状态:以约 10 Hz 的频率限制光标的移动速度 vec3 字段(位置、速度、力),并重新发送零力保活指令。

参数​

名称默认值用途
URIws://localhost:10001WebSocket 仿真通道的 URL
PRINT_EVERY_MS100控制台输出限速
会话配置文件名称co.haply.inverse.tutorials:print-inverse3在Haply Hub中标识该仿真

读取的状态字段​

摘自 data.inverse3[0].state:

  • cursor_position、cursor_velocity、current_cursor_force —— 均为 vec3
  • transform —— 工作空间变换;作为子对象,包含 position(vec3)、rotation(quaternion)和 scale(vec3)
部分语义更新

等于其单位默认值的子字段(position: {0,0,0}、rotation: {w:1,x:0,y:0,z:0}、scale: {1,1,1})为节省带宽,会从负载中省略。读取时务必提供默认值(例如在 C++ 中使用 .value("position", default_pos),在 Python 中使用 .get("position", default_pos))。若要始终接收每个字段,请启用 serialization/explicit_fields。

发送 / 接收​

WebSocket 循环:接收一个状态帧,构建并并发回一个指令帧。第一个指令帧携带会话握手信息以及零力的 set_cursor_force 保活指令;此后每一帧仅携带保持活动指令(会话信息已删除)。

单一异步循环——recv() → 构建指令 → send() → 重复。

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"]
request_msg = {
"session": {"configure": {"profile": {
"name": "co.haply.inverse.tutorials:print-inverse3"}}},
"inverse3": [{
"device_id": device_id,
"commands": {"set_cursor_force":
{"vector": {"x": 0.0, "y": 0.0, "z": 0.0}}},
}]
}

await websocket.send(json.dumps(request_msg))
request_msg.pop("session", None) # one-shot handshake

命令行参数(Python)​

Python 变体接受两个参数,用于更改教程的输出内容:

参数作用
--full以格式化方式输出每个状态帧中的原始 JSON 负载数据,而非单行摘要。这有助于了解服务会输出哪些字段。
--query-config在每个发出的周期中重新注入 session.force_render_full_state: {},使服务在每一帧中都重新输出完整的快照(包括 config 块——设备类型、固件、预设、安装方式、过滤器等)。如果不使用该参数,config 仅出现在第一帧中,后续帧均为流式增量数据。

这两个参数可以组合使用——python 01-haply-inverse-print-inverse3.py --full --query-config 将在每个周期输出包含可见 config 完整的 JSON 负载数据,在通过Haply Hub 或 HTTP API 实时观察设置变化时非常实用。有关底层 WebSocket 命令,请参阅 session.force_render_full_state。

C++ 变体不支持这些参数——它们始终只输出单行摘要,并且 config 仅在第一帧中接收。

随 SDK 安装程序一同提供

教程 01 也随 SDK 一起安装在本地——请在服务安装目录下的 tutorials/01-haply-inverse-print-inverse3/ 中查找。

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

相关内容: WebSocket 协议 · 控制命令(set_cursor_force) · 会话 · 类型(vec3)