本文へスキップ

01. 「Inverse3 」の出力

シミュレーションのWebSocketに接続し、サービスから報告される最初のInverse3のカーソルの位置、速度、力をストリーミングします。

学習内容:

  • WebSocket接続を開き、初期のフルステートメッセージを受信する
  • セッションが継続して動作するように、ゼロフォース set_cursor_force 「キープアライブ」を送信
  • Haply Hubがシミュレーションを認識できるように、セッションプロファイルを登録する
  • 最初のメッセージでのみ実行されるハンドシェイクパターン — 最初の送信後に session/configure を削除する
  • 部分更新のセマンティクスによるワークスペース transform(位置、回転、スケール)の読み取り
  • コンソール出力を読みやすい速度に調整する

ワークフロー​

  1. ws://localhost:10001WebSocket接続を開きます。このサービスは、接続されたデバイスの一覧を表示します。 全体状態フレームを直ちに送信します。
  2. 最初のフレームにおける最初の Inverse3 の device_idを選択し、2つの部分からなるリクエストメッセージを作成します:
    • session.configure.profile.name — Haplyシミュレーションを登録します。
    • ゼロベクトルを用いたデバイスごとの set_cursor_force コマンド。サービスはこれをキープアライブとして使用し、コマンドが到着し続ける限り、ステータスフレームを送信し続けます。
  3. メッセージを再送信します。次のティックが始まる前に session フィールドを削除します — セッションプロファイルは1回限りのハンドシェイクであるため、その後のティックではコマンドのみを送信します。
  4. その後、各状態フレームごとにカーソル vec3 フィールド(位置、速度、力)を約10 Hzに制限して出力し、ゼロ力のキープアライブを再度送信します。

パラメータ​

名前デフォルト値用途
URIws://localhost:10001シミュレーションチャンネルのWebSocket URL
PRINT_EVERY_MS100コンソール出力のスロットリング
セッションプロファイル名co.haply.inverse.tutorials:print-inverse3Haply 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のバリエーションでは、チュートリアルの出力を変更する2つのフラグがサポートされています:

フラグ効果
--full一行の要約の代わりに、すべての状態フレームの生のJSONペイロードを見やすく出力します。サービスがどのフィールドを出力しているかを確認するのに役立ちます。
--query-configすべてのティックごとに session.force_render_full_state: {}を再度注入することで、サービスがすべてのフレームで config ブロック(デバイスタイプ、ファームウェア、プリセット、マウント、フィルターなど)を含むスナップショット全体を再度エクスポートするようにします。このフラグがない場合は configは最初のフレームでのみ送信され、それ以降のフレームはストリーミングデルタです。

この2つのフラグは併用可能です — python 01-haply-inverse-print-inverse3.py --full --query-configを実行すると、ティックごとに configとマークされたJSONペイロード全体が出力されます。Haply HubやHTTP APIを通じて設定がリアルタイムで変更される様子を確認する際に役立ちます。これに基づくWebSocketコマンドは session.force_render_full_stateを参照してください。

C++の変形ではこのフラグは提供されていません。常に1行の要約のみが出力され、 configは最初のフレームでのみ受け取ります。

SDKインストーラーに同梱されています

チュートリアル 01 は、SDK とともにローカルにもインストールされています — サービスのインストールディレクトリ内の tutorials/01-haply-inverse-print-inverse3/で確認できます。

出典: Python·C++·C++ Glaze

関連: WebSocketプロトコル ・ 制御コマンド (set_cursor_force) ・ セッション ・ 型 (vec3)