本文へスキップ
バージョン: 3.5.x

WebSocketプロトコル

シミュレーションチャネルは、ポート10001上のWebSocket接続です。これは、 アプリケーションとサービス間のリアルタイムなコマンド/ステータスループを伝送します。

基本ルール:1つのメッセージにつき1つの返信

このサービスは、クライアントから受信したメッセージ1件につき、 正確に1回の状態更新を送信します:

ポーリングも、サブスクリプションも、アウトオブバンドのプッシュ通知もありません。配信間隔は 完全に送信レートによって決まります。


ステップ1 — 初期インベントリ(サービスからの最初のメッセージ)

接続時に、サービスは 完全なスナップショット ~を含む config, state, そして status 検出したデバイスごとに:

{
"session_id": 7,
"inverse3": [
{
"device_id": "049D",
"config": {
"type": "inverse3",
"port": "COM12",
"device_info": { "major_version": 7, "minor_version": 4, "id": "049D", "device_type": 4, "uuid": "…" },
"extended_device_id": "…",
"extended_firmware_version": "…",
"gravity_compensation": { "enabled": true, "scaling_factor": 1.0 },
"handedness": "right",
"streaming_mode": "USB",
"torque_scaling": { "enabled": true },
"home_return": { "enabled": false },
"preset": "defaults",
"basis": { "permutation": "XYZ" },
"mount": { "position": { "x": 0, "y": 0, "z": 0 }, "rotation": { "w": 1, "x": 0, "y": 0, "z": 0 }, "scale": { "x": 1, "y": 1, "z": 1 } },
"filters": {
"force_gate": { "gain": 0.3 },
"damping": { "scalar": 0.0 }
}
},
"state": {
"cursor_position": { "x": 0.0, "y": -0.12, "z": 0.15 },
"cursor_velocity": { "x": 0.0, "y": 0.0, "z": 0.0 },
"angular_position": { "a0": 0.0, "a1": 0.0, "a2": 0.0 },
"angular_velocity": { "a0": 0.0, "a1": 0.0, "a2": 0.0 },
"body_orientation": { "w": 1.0, "x": 0.0, "y": 0.0, "z": 0.0 },
"current_cursor_force": { "x": 0.0, "y": 0.0, "z": 0.0 },
"current_cursor_position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"current_angular_torques": { "a0": 0.0, "a1": 0.0, "a2": 0.0 },
"current_angular_position": { "a0": 0.0, "a1": 0.0, "a2": 0.0 },
"control_domain": "cartesian",
"control_mode": "idle",
"transform": { "position": { "x": 0, "y": 0, "z": 0 }, "rotation": { "w": 1, "x": 0, "y": 0, "z": 0 }, "scale": { "x": 1, "y": 1, "z": 1 } },
"transform_velocity": { "position": { "x": 0, "y": 0, "z": 0 }, "rotation": { "w": 1, "x": 0, "y": 0, "z": 0 }, "scale": { "x": 0, "y": 0, "z": 0 } }
},
"status": {
"calibrated": true,
"in_use": false,
"power_supply": true,
"ready": true,
"started": true
}
}
],
"verse_grip": [],
"wireless_verse_grip": []
}

3つのブロックは、更新頻度がそれぞれ異なります:

ブロック含まれる変更点
configファームウェア情報、プリセット、基本設定、マウント、フィルターごくまれに — 明示的な設定変更が行われた場合のみ
state位置、速度、力、向き、変換各ティック(高頻度)
status準備完了、校正済み、電源接続、使用中時折(頻度は低い)

ステップ 2 — 最初のコマンドを送信する

初期インベントリを解析してデバイスIDを確認し、セッションプロファイル、初期設定、および/または制御コマンドを含むメッセージを返信します:

{
"session": {
"configure": {
"profile": { "name": "co.haply.inverse.tutorials:hello-floor" }
}
},
"inverse3": [
{
"device_id": "049D",
"configure": {
"preset": { "preset": "arm_front_centered" }
},
"commands": {
"set_cursor_force": { "vector": { "x": 0.0, "y": 0.0, "z": 0.0 } }
}
}
]
}

ステップ3 — その後の状態の更新

最初のやり取りの後、このサービスは state + status (いいえ config) 設定の変更によってスナップショットの完全なプッシュがトリガーされない限り:

{
"session_id": 7,
"inverse3": [
{
"device_id": "049D",
"state": { "cursor_position": {}, "cursor_velocity": {},},
"status": { "ready": true, "calibrated": true,}
}
]
}

ステップ4 — 繰り返す

コマンドを送信 → 状態の更新を受信。このループは、送信レートに応じて繰り返されます。


configurecommands

送信メッセージ内の各デバイスエントリには、2つのマップを含めることができます:

地図目的粘り強さ
configureワンショット設定:プリセット、ベース、マウント、フィルター、モジュール設定変わるまで記憶される
commands1ティックごとの制御:力、位置、トルク一度使ったら、あとは忘れてしまっても大丈夫

参照 セッション設定 の 完全なリストは configure キー、および 制御コマンド ~のために ~ commands エントリー。

set_transform は特殊なケースです

set_transform ~の下に住んでいる commands しかし、それは 持続的な — このサービスは、 新しい値を送信するまで、前回の値を保持し続けます。これは、その目的が シーンナビゲーションにあるためです。シーンナビゲーションでは、カメラの移動中にトランスフォームをストリーミングしますが、 ボタンを押す間隔では前回の位置を維持したいからです。


について execute

いずれか configure または commands エントリには以下を含めることができます "execute": false ~を 提供するため 解析および検証 適用せずにペイロードを

{
"inverse3": [{
"device_id": "049D",
"configure": {
"preset": { "preset": "arm_front", "execute": true },
"damping": { "scalar": 0.0, "execute": false }
}
}]
}

これは、次のような場合に役立ちます リフレクションベースのシリアライザ (例:Unityの JsonUtility) 常にすべてのフィールドを出力する場合:未使用のエントリを execute: false そうすることで、 実際の設定を上書きしないようにします。デフォルトは true — フラグを省略すると、 「通常通り適用する」という意味になります。


警告

すでにコマンドを送信している場合は、確認しないでください

probe_position そして probe_orientation これらは、制御コマンドを送信しないセッション(例:Haply )向けの、監視専用のキープアライブです。もしあなたのセッションが すでに送信している場合は set_cursor_force, set_cursor_positionなど、 プローブも 送らないでください — デバイスの状態はすでにすべての応答に含まれています。両方を混在させると、 帯域幅を無駄にするだけでなく、 session-probe-dropped イベント。

不明なキーは黙って無視されます

コマンドが反応しない場合は、フィールド名が間違っている可能性があります。 現在、本サービスでは認識できないJSONキーをエラーを出さずに無視しています。 サービスログを確認し、APIリファレンスと照らし合わせてフィールド名を確認してください。 この動作は、将来のバージョンで変更される予定です。