WebSocket-Protokoll
Der Simulationskanal ist eine WebSocket-Verbindung aufPort 10001. Er dient dem Echtzeit-Befehls- und Statusaustausch zwischen Ihrer Anwendung und dem Dienst.
Grundregel: Jede Nachricht entspricht einer Antwort
Der Dienst sendet fürjedevom Client empfangeneNachrichtgenaueine Statusaktualisierung:
Es gibt keine Abfragen, Abonnements oder Out-of-Band-Benachrichtigungen. Der Aktualisierungsrhythmus richtet sich ausschließlich nach Ihrer Sendefrequenz.
Schritt 1 – Erstliste (die erste Nachricht vom Dienst)
Bei der Verbindung sendet der Dienst für jedes erkannte Gerät eineVollständiger Schnappschuss, das Folgendes enthält: 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": []
}
Die Aktualisierungshäufigkeit dieser drei Datenblöcke ist unterschiedlich:
| Datenblock | Inhalt | Änderungshäufigkeit |
|---|---|---|
config | Firmware-Informationen, Voreinstellungen, Basis, Mount, Filter | Selten – nur bei einer expliziten Änderung der Konfiguration |
state | Position, Geschwindigkeit, Kraft, Lage, Transformation | Pro Tick (Hochfrequenz) |
status | Bereit, kalibriert, Stromversorgung, in_use | Gelegentlich (selten) |
Schritt 2 – Den ersten Befehl senden
Analysieren Sie die anfängliche Liste, um Ihre Geräte-ID zu ermitteln, und senden Sie anschließend eine Nachricht zurück, die Ihre Sitzungskonfiguration sowie etwaige Anfangskonfigurationen und/oder Steuerbefehle enthält:
{
"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 } }
}
}
]
}
Schritt 3 – Weitere Statusaktualisierungen
Nach der ersten Interaktion sendet der Dienst nur dann Daten, wenn Konfigurationsänderungen die Übertragung eines vollständigen Snapshots auslösen. state + status(ohne config):
{
"session_id": 7,
"inverse3": [
{
"device_id": "049D",
"state": { "cursor_position": { … }, "cursor_velocity": { … }, … },
"status": { "ready": true, "calibrated": true, … }
}
]
}
Schritt 4 – Wiederholen
Befehl senden → Statusaktualisierung empfangen. Der Zyklus läuft entsprechend deiner Sendegeschwindigkeit weiter.
configure und commands
In den von dir gesendeten Nachrichten kann jeder Geräteeintrag zwei Zuordnungen enthalten:
| Abbildung | Verwendungszweck | Beständigkeit |
|---|---|---|
configure | Einmalige Einstellungen: Voreinstellungen, Basis, Einbindung, Filter, Modulkonfiguration | Gültig, bis eine Änderung erfolgt |
commands | Zyklusweise Regelung: Kraft, Position, Drehmomente | Nur einmal anwendbar, danach verliert es seine Wirksamkeit |
Zu configure Eine vollständige Liste der Tasten finden Sie unter Sitzungskonfiguration; bezüglich commands Eintrag, siehe Steuerbefehle。
set_transform Das ist ein Sonderfall.set_transform gelegen in commands unten, aber es istDauerhaftigkeit——Der Dienst behält den letzten Wert so lange bei, bis du einen neuen Wert sendest. Der Grund dafür ist, dass er für die Szenennavigation verwendet wird: Du sendest die Transformationen während der Kamerabewegung in Echtzeit, möchtest aber die letzte Position zwischen zwei Tastendrücken beibehalten.
execute Logo
Jedes configure oder commands Einträge können Folgendes enthalten "execute": false, damit der DienstAnalyse und ÜberprüfungLaden, ohne es anzuwenden.
{
"inverse3": [{
"device_id": "049D",
"configure": {
"preset": { "preset": "arm_front", "execute": true },
"damping": { "scalar": 0.0, "execute": false }
}
}]
}
Das gilt fürReflektionsbasierter Serializer(zum Beispiel Unity) JsonUtility) Sehr nützlich, denn solche Serializer geben immer alle Felder aus: Nicht verwendete Einträge werden auf execute: false, damit sie die tatsächliche Konfiguration nicht überschreiben. Der Standardwert lautet true——Wird dieses Symbol weggelassen, bedeutet dies „normale Anwendung“.
Warnung
probe_position und probe_orientation Dies sind reine Keep-Alive-Nachrichten zur Überwachung, die für Sitzungen gelten, bei denen keine Steuerbefehle gesendet werden (z. B. „ Haply -Hub“). Wenn Ihre Sitzung bereits set_cursor_force、set_cursor_position Befehle wie,Bitte senden Sie nicht erneut gleichzeitig mehrere Testnachrichten.——Der Gerätestatus ist bereits in jeder Antwort enthalten. Die gleichzeitige Verwendung beider Optionen verschwendet Bandbreite und kann zudem dazu führen, dass session-probe-dropped Ereignis.
Wenn ein Befehl offenbar keine Wirkung zeigt, ist der Feldname höchstwahrscheinlich falsch. Der Dienst ignoriert derzeit nicht erkannte JSON-Schlüssel, ohne eine Fehlermeldung auszugeben. Bitte überprüfen Sie das Dienstprotokoll und vergleichen Sie die Feldnamen mit der API-Referenz. Dieses Verhalten soll in zukünftigen Versionen geändert werden.