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 — 繰り返す
コマンドを送信 → ステータスの更新を受信。このループは、送信速度に応じて継続されます。
configure と commands
送信したメッセージにおいて、各デバイスエントリには2つのマッピングを含めることができます:
| マッピング | 用途 | 持続性 |
|---|---|---|
configure | 初期設定:preset、basis、mount、filters、モジュール設定 | 変更されるまで有効とする |
commands | 周期ごとの制御:力、位置、トルク | 1回のみ有効で、その後は失効します |
について configure キーの完全な一覧については、以下を参照してください。 会話構成;関連して commands 項目については、以下を参照してください。 制御コマンド。
set_transform 例外ですset_transform 所在地: commands 以下ですが、それは持続的な——このサービスは、新しい値を送信するまで、最後の値を保持し続けます。これは、シーンナビゲーションを目的としているためです。つまり、カメラを移動させる際にトランスフォームをストリーミング送信しつつ、2回のキー押下の間は最後の位置を保持しておきたいのです。
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 Hubなど)に適用されます。セッションがすでに送信を行っている場合は、 set_cursor_force、set_cursor_position などの命令、探査メッセージを同時に送信するのはお控えください——機器の状態は各レスポンスに含まれています。これらを併用すると帯域幅を無駄にするだけでなく、 session-probe-dropped 事件。
あるコマンドがまったく効果がないように見える場合、フィールド名が間違っている可能性があります。現在、本サービスでは、認識できない JSON キーをエラーを返さずに無視しています。サービスのログを確認し、API リファレンスと照らし合わせてフィールド名を確認してください。この動作は、将来のバージョンで変更される予定です。