メインコンテンツへスキップ

WebSocketプロトコル

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

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

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

ポーリングも、サブスクリプションも、アウト・オブ・バンド・プッシュもありません。クロックは、送信周波数によって完全に決定されます。


ステップ 1 — 初期状況把握(サービスからの最初の通知)​

接続の確立時に、サービスは 完全なスナップショット mit config, state und 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 (ohne config)、ただし、設定の変更によってスナップショットの完全なプッシュがトリガーされる場合はこの限りではありません:

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

ステップ 4 — 繰り返す​

コマンドを送信すると → ステータスの更新情報が返されます。ループは、設定された送信周波数で継続して実行されます。


configure 対 commands​

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

地図Zweck持続性
configure初期設定:プリセット、基本設定、取り付け、フィルター、モジュール構成変更されるまで保存されます
commands1ティックごとの制御:力、位置、トルク一度使ったら、その後は忘れてしまう

の完全なリストは configure- 鍵は以下の場所にあります セッション設定、そしてその commands-「以下」のエントリ 制御命令.

注意
set_transform は特殊なケースである

set_transform に属する commands、だが 持続的な — このサービスは、新しい値を送信するまで、最後の値を保持します。これは、このサービスの目的がシーン内ナビゲーションにあるためです。つまり、カメラの移動中に変換をストリーミングしますが、入力の合間には最後の位置を保持しておきたいのです。


「Das Flag」 execute​

すべてのエントリ configure oder commands kann "execute": false が含まれており、これによりサービスがペイロードを 解析および検証、それを適用せずに。

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

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


警告​

すでにコマンドを送信している場合は、プローブを送信しないでください

probe_position und probe_orientation これらは、制御コマンドを送信しないセッション(例:Haply ハブ)向けの、純粋な監視用キープアライブです。セッションがすでに set_cursor_force, set_cursor_position など、送信します、 追加のサンプルは送らないでください — いずれにせよ、デバイスの状態はすべての応答に含まれています。両方を同時に送信すると帯域幅を無駄にし、さらに session-probe-dropped-イベントをトリガーする。

未知のキーは黙って無視されます

コマンドが効果を発揮していないように見える場合は、フィールド名が間違っている可能性があります。現在、このサービスは未知のJSONキーをエラーメッセージを表示せずに無視します。サービスのログを確認し、フィールド名をAPIリファレンスと照らし合わせてみてください。この動作は、将来のバージョンで変更される予定です。