Zum Hauptinhalt springen

Simulationskanal

Überblick​

Ein Simulationskanal ist ein hochfrequenter, bidirektionaler WebSocket-Kanal, der zum Austauschvon Gerätestatusinformationensowie zum Senden vonSitzungs- oderGerätebefehlendient.

Standard-URL: ws://localhost:10001

Der Port kann in der Konfiguration geändert werden.

Kernvereinbarungen (wichtig):

  • Wenn sich ein Client verbindet, sendet der Dienst eine „Initial Inventory“-Nachricht, die eine vollständige Geräteliste enthält.
  • Danach sendet der Server fürjedevom Client gesendeteNachrichtgenaueine „State Update“-Nachricht.
  • Jedes „State Update“ enthält den Status (state und status)allerGeräte.
Modul

Auf dieser Seite werdendie wichtigstenProtokolle und Befehle der Simulationskanäle vorgestellt.

Weitere Module/Funktionen können über ihre jeweiligen Befehle und/oder Statusfelder registriert und das System erweitert werden. Diese Inhalte werden separat im Abschnitt „Module“ beschrieben.

Vereinbarungsregeln​

Jede Client-Nachricht entspricht einer Antwort​

Fürjedevom Client gesendeteNachrichtsendet der Diensteine „State Update“-Nachricht, die den StatusallerGeräte enthält.

Das bedeutet:

  • Wenn Sie eine aktuelle Momentaufnahme des Gerätestatus benötigen, müssen Sieeinen Befehlsenden (entweder einen Sitzungsbefehl, einen Abfragebefehl oder einen Gerätebefehl).
  • Die Funktionsweise dieses Kanals ähnelt einem durch Client-Nachrichten gesteuerten „Tick“-Zyklus.

Abfrage ohne Kraftanwendung (Abfragebefehl)​

Wenn Sie Zustandsänderungen beobachten möchten,ohne Kräfte aufzubringenoder die Simulationsparameter zu ändern, verwenden Sie bitte den Befehl „Detect“:

  • probe_position verwendet für inverse3
  • probe_orientation Für Verse-Griffe

Der Abfragebefehl enthält keine Befehlsdaten, sondern dient ausschließlich dazu, Geräteinformationen abzufragen, damit die Positions- und Richtungsdaten im nächsten „State Update“ auf dem neuesten Stand sind.

Möglicherweise benötigen Sie den Befehl „detect“ nicht.

Der Steuerbefehl wurde gesendet (set_cursor_force、set_cursor_position (usw.) SimulationssitzungenNicht erforderlichSenden eines Abfragebefehls – Der Gerätestatus ist stets im Antwort-Frame enthalten. Der Abfragebefehl dient dazu,Nur ÜberwachungSitzungen (z. B. „ Haply Hub“), bei denen der Gerätestatus abgefragt werden muss, ohne dass das Gerät angesteuert wird.

Konfiguration und Status​

  • Ausgangsbestand Die Meldung enthält Informationen zum Gerät config、state und status。
  • üblich Aktuelles aus dem Bundesstaat Die Meldung enthält Informationen zum Gerät state und status。

Wenn Sie erneut einen vollständigen Snapshot mit den Konfigurationsdaten abrufen möchten, verwenden Sie bitte session.force_render_full_state。

configure und commands​

Gerätemeldungen unterstützen zwei unabhängige Zuordnungen:configure und commands。Sie haben unterschiedliche Verwendungszwecke:

AbbildungVerwendungszweckSendehäufigkeit
configureEinmalige, dauerhafte Konfiguration: Voreinstellungen, Referenzwerte, Installationsart, Filter, ModuleinstellungenEinmal senden oder bei Änderungen senden
commandsTick-basiert, nicht persistent: Kraft, Position, DrehmomentEs muss bei jedem Tick gesendet werden

commands Einträge in (set_cursor_force、set_cursor_position、set_angular_torques、set_angular_position)Wird bei jedem Tick einmal angewendet und nicht gespeichert——Wenn die Übertragung beendet wird, lässt die Wirkung sofort nach, und das Gerät kehrt in den Ruhezustand zurück. Für Inhalte, die über mehrere Ticks hinweg wirksam bleiben sollen, ohne dass eine wiederholte Übertragung erforderlich ist, verwenden Sie bitte configure。

Anmerkung
set_transform Das ist ein Sonderfall.

set_transform gelegen in commands unten, aber es istdauerhaft——Der Dienst behält die zuletzt von Ihnen gesendete Transformation so lange bei, bis Sie eine neue Transformation senden. SieNicht nötigEs wird bei jedem Tick gesendet. Da es jedoch für die Kamera-/Szenennavigation vorgesehen ist, wird es bei der Verschiebung der Szene durch den Benutzer (z. B. durch das Senden einer Transformation pro Bild) kontinuierlich mit der Tick-Frequenz gesendet – genau das ist das erwartete Nutzungsmuster für die Navigation bei kontinuierlicher Bewegung.

Koordinatensystem​

Haply Standardmäßig wirddas rechtshändige Koordinatensystemverwendet, wobeidie Z-Achse nach oben zeigt.

Zwei „configure“-Einträge beeinflussen die Interpretation und die Art der Rückgabe der Koordinaten:

  • session.configure.basis: Ändern der Zuordnung zwischen den Koordinaten von „ Haply “ und dem Koordinatensystem der Anwendung (siehe unten Referenzwert).
  • inverse3[*].configure.preset: Wählen Sie eine benannte Werkseinstellung aus, um den Arbeitsbereichsursprung festzulegen (z. B. arm_front_centered wird (0, 0, 0) (in der Mitte des Arbeitsbereichs platzieren). Weitere Informationen finden Sie im Abschnitt „Configure“ der jeweiligen Geräte.

Nachrichtenformat​

In diesem Abschnitt werden die Struktur der übergeordneten Nachrichtenhüllen und die Nachrichtentypen vorgestellt. Ausführliche Beispiele finden Sie weiter unten in diesem Dokument.

Gerätegruppen​

Die Nachrichten werden auf der obersten Ebene nach Gerätetyp gruppiert (z. B. inverse3、verse_grip、wireless_verse_grip). Jeder Gerätetyp-Schlüssel entspricht einem Array, das aus den jeweiligen Geräteobjekten besteht.

Ersteinbestand (Server → Client)​

Wird unmittelbar nach dem Aufbau der WebSocket-Verbindung einmal gesendet.

Jeder Eintrag enthält:

  • device_id
  • config
  • state
  • status

Siehe auch:Beispiel: Last des Anfangsbestands

Status-Update (Server → Client)​

Jede Client-Nachricht wird einmal gesendet.

Jeder Eintrag enthält:

  • device_id
  • state
  • status

Siehe auch:Beispiel: State-Update-Last

Sitzungsbefehlsumschlag (Client → Server)​

Sitzungsbefehle sind Operationen, die auf die aktuelle Verbindung bzw. Sitzung angewendet werden undnicht auf ein bestimmtes Gerät abzielen.

{
"session": {
"<command_name>": {
"...": "..."
}
}
}

Gerätebefehlsumschlag (Client → Server)​

Gerätebefehle werden in Form eines Arrays unter dem Schlüssel „Gerätetyp“ gesendet, sodass mit einer einzigen Nachricht Befehle gleichzeitig an ein oder mehrere Geräte gesendet werden können. Jeder Geräteeintrag unterstützt gleichzeitig configure Abbildung und commands Abbildung.

{
"<device_type>": [
{
"device_id": "<id>",
"configure": {
"<config_key>": { "...": "..." }
},
"commands": {
"<command_name>": { "...": "..." }
}
}
]
}

Sie können mehrere Einträge in eine Nachricht aufnehmen, um Befehle gleichzeitig an mehrere Geräte desselben Typs zu senden. Bitte beachten Sie, dasscommands Es handelt sich um ein Wörterbuch, das für ein bestimmtes Gerät mehrere Befehle enthalten kann, wobei jedoch von jedem Befehlstyp nur einer vorhanden sein darf.

execute Feld​

Jeder Befehl oder jeder „configure“-Eintrag akzeptiert ein optionales "execute" Boolesche Werte (Standardwert: true). Einstellungen "execute": false Danach wird dieser Eintrag zwar ausgewertet, aber nicht angewendet. Dies gilt für reflektionsbasierte Serializer, die stets alle Felder ausgeben (z. B. Unity JsonUtility) Sehr nützlich.

"set_cursor_force": { "execute": false, "vector": { "x": 0.0, "y": 0.0, "z": 0.0 } }

Befehlsübersicht​

Gespräch​

Vollständigen Status zwangsweise rendern​

Fordern Sie einen Status- und Konfigurations-Snapshot aller Geräte an.

{
"session": {
"force_render_full_state": {}
}
}

Sitzungskonfiguration​

Persistente Konfiguration auf Sitzungsebene erfolgt über session.configure Senden. Dies entspricht der Geräteebene configure entsprechende Abbildungsmodi.

Konfigurationsdatei​

Legen Sie den Namen des Sitzungsprofils fest. Anhand dieses Namens erkennt der „Haply Hub“ die Simulation und speichert die gerätespezifischen Feineinstellungen für jede Anwendung.

{
"session": {
"configure": {
"profile": {
"name": "my_profile"
}
}
}
}
Referenzzuordnung (auf Sitzungsebene)​

Legen Sie eine Referenzzuordnung für die gesamte Sitzung fest. Die Referenzzuordnung beschreibt, wie Koordinaten aus „ Haply “ in das Koordinatensystem Ihrer Anwendung umgewandelt werden. Nach der Festlegung werden alle Gerätestatuswerte in dieser Referenz zurückgegeben, und alle von Ihnen gesendeten Werte werden anhand dieser Referenz interpretiert.

Die Zeichenfolge wird im Koordinatensystem mit der rechten Seite von Haply als Bezugspunkt und der Z-Achse als Aufwärtsrichtung dargestellt, d. h. X、Y、Z eine Anordnung, die wahlweise mit + oder - Als Präfix. Beispiel:

  • XYZ、ZYX、+Y-Z+X、X-ZY
  • YZX Zeigen Sie Ihre Y Die Achse entspricht der rechten Seite von Haply , Ihre Z Die Achse entspricht der Vorderseite von „ Haply “, Ihre X Die Achse befindet sich oberhalb von „ Haply “.

Beispiel für die Z-Achse nach links (Unreal,X-YZ):

{
"session": {
"configure": {
"basis": { "permutation": "X-YZ" }
}
}
}
Hinweis
von session.set_basis Migration

Alte Version session.set_basis und session.configure.basis Die Konvention für die Achsenbezeichnungen hat sich geändert. Eine Anordnung, die unter dem alten Befehl gültig war, kann unter dem neuen Befehl zu einer umgekehrten Transformation führen – kehren Sie bei Bedarf die Vorzeichen der entsprechenden Achsen um (zum Beispiel X-ZY werden zu XZ-Y).

Alle Gerätebefehle​

Erkennung (alle Geräte)​

Mit dem Abfragebefehl können die aktuellen Positions- und Lageinformationen abgefragt werden, ohne dass Kräfte ausgeübt oder andere Änderungen an der Simulation vorgenommen werden müssen.

  • inverse3:probe_position
  • Verse-Griff(verse_grip、wireless_verse_grip):probe_orientation
{
"inverse3": [
{
"device_id": "049D",
"commands": {
"probe_position": {}
}
}
],
"verse_grip": [
{
"device_id": "049D",
"commands": {
"probe_orientation": {}
}
}
],
"wireless_verse_grip": [
{
"device_id": "049D",
"commands": {
"probe_orientation": {}
}
}
]
}

Einstellungen anpassen (alle Geräte)​

Richtungswechsel im Arbeitsbereich für das Gerät festlegen (vom Geräteraum in den Anwendungsraum).

und andere commands Die Einträge unterscheiden sich,set_transform Jadauerhaft——Der Dienst speichert den zuletzt von Ihnen gesendeten Wert so lange, bis Sie einen neuen Wert senden. Sie müssen ihn nicht bei jedem Tick senden; da er jedoch für die Kamera- und Szenennavigation vorgesehen ist, wird bei kontinuierlichen Bewegungen, wie z. B. beim Verschieben der Szene durch den Benutzer, eine kontinuierliche Übertragung im Tick-Takt (z. B. das Senden einer Transformation pro Bild) als erwartete Verwendung angesehen.

{
"inverse3": [
{
"device_id": "049D",
"commands": {
"set_transform": {
"transform": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 },
"scale": { "x": 1.0, "y": 1.0, "z": 1.0 }
}
}
}
}
]
}
Verse Grip / kabelloser Verse Grip

Bei den Geräten „Verse Grip“ und „Wireless Verse Grip“ gilt dies nur für die Umwandlung von rotation Die Größe spielt eine Rolle – der Griff meldet lediglich die Lage, daher position und scale Es gibt keine Inhalte, die gezoomt oder verschoben werden können.position und scale Die Felder werden lediglich akzeptiert (und im Snapshot angezeigt), um die Struktur von Inverse3 beizubehalten; üblicherweise werden sie als Einheitswerte beibehalten (position = {0,0,0},scale = {1,1,1}).

Inverse3 Gerätekonfiguration​

Konfigurationseinträge über configure Zuordnung senden. Sie sind dauerhaft – es reicht, sie einmal zu senden, oder sie bei Änderungen erneut zu senden.

Voreinstellungen​

{
"inverse3": [
{
"device_id": "049D",
"configure": {
"preset": { "preset": "arm_front_centered" }
}
}
]
}

Mögliche Werte:device_defaults、arm_front、arm_front_centered、led_front、led_front_centered、custom。

Referenzzuordnung (auf Geräteebene)​

{
"inverse3": [
{
"device_id": "049D",
"configure": {
"basis": { "permutation": "ZXY" }
}
}
]
}

Installation​

Konfigurieren Sie die Geräteinstallation. Hinweis mount intern transform Verpackungsschicht.

{
"inverse3": [
{
"device_id": "049D",
"configure": {
"mount": {
"transform": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 },
"scale": { "x": 1.0, "y": 1.0, "z": 1.0 }
}
}
}
}
]
}
Das Schema des Felds „Installation“ ist asymmetrisch

BefehlAuf einer Seite (vom Client zum Server) erfolgt eine Umwandlung:"mount": { "transform": { ... } }。 SchnappschussAuf der einen Seite (vom Server zum Client) ist die Struktur flach:"mount": { "position": {...}, "rotation": {...}, "scale": {...} }。 Dies ist beabsichtigt – Befehle verwenden eine einheitliche Verpackungsstruktur, während Snapshots die Transformation direkt serialisieren. Achten Sie darauf, die Struktur des Snapshots nicht in die Befehls-Nutzlast zu kopieren.

Dämpfung​

Steuerung der gleichmäßigen Dämpfung und/oder der richtungsabhängigen Dämpfung. Es muss mindestens ein Feld enthalten sein.

{
"inverse3": [
{
"device_id": "049D",
"configure": {
"damping": { "scalar": 0.5 }
}
}
]
}

Sie können auch eine Richtungsdämpfung einstellen oder beides gleichzeitig:

"damping": { "scalar": 0.5, "vector": { "x": 0.0, "y": 1.0, "z": 0.0 } }

Kraftgesteuert​

Stellen Sie den Dämpfungsfaktor für die Kraftsteuerung ein (0,0 bis 1,0).

{
"inverse3": [
{
"device_id": "049D",
"configure": {
"force_gate": { "gain": 0.3 }
}
}
]
}

Inverse3 Befehl​

An inverse3 Das Gerät sendet einen Befehl. Bitte geben Sie inverse3 Die Zeile enthält ein device_id Übereinstimmende Einträge. Der Befehl wird pro Tick wirksam und muss bei jedem Tick erneut gesendet werden, um gültig zu bleiben.

Befehle an ein einzelnes Gerät senden:

{
"inverse3": [
{
"device_id": "049D",
"commands": {
"set_cursor_force": {
"vector": {
"x": 1.0,
"y": 2.0,
"z": 3.0
}
}
}
}
]
}

Befehle in einer Nachricht an mehrere Geräte senden:

{
"inverse3": [
{
"device_id": "049D",
"commands": {
"set_cursor_force": {
"vector": {
"x": 1.0,
"y": 2.0,
"z": 3.0
}
}
}
},
{
"device_id": "049E",
"commands": {
"set_cursor_force": {
"vector": {
"x": 1.0,
"y": 2.0,
"z": 3.0
}
}
}
}
]
}

Cursorposition festlegen​

{
"inverse3": [
{
"device_id": "049D",
"commands": {
"set_cursor_position": {
"position": {
"x": 1.0,
"y": 2.0,
"z": 3.0
}
}
}
}
]
}

Cursorkraft einstellen​

{
"inverse3": [
{
"device_id": "049D",
"commands": {
"set_cursor_force": {
"vector": {
"x": 1.0,
"y": 2.0,
"z": 3.0
}
}
}
}
]
}

Winkelposition einstellen​

{
"inverse3": [
{
"device_id": "049D",
"commands": {
"set_angular_position": {
"angles": {
"a0": 1.0,
"a1": 2.0,
"a2": 3.0
}
}
}
}
]
}

Drehmoment einstellen​

{
"inverse3": [
{
"device_id": "049D",
"commands": {
"set_angular_torques": {
"torques": {
"a0": 1.0,
"a1": 2.0,
"a2": 3.0
}
}
}
}
]
}

Verse Grip-Konfiguration​

Verse Grip und die kabellosen Verse Grip-Geräte unterstützen dieselben Funktionen wie Inverse3 configure Taste, die dazu dient, preset、basis und mount。

Erweiterung „Verse Grip“​

set_extension_data Der Befehl ist Teil des Verse-Grip-Erweiterungsprotokolls und gilt für Griffversionen, die das Kommunikationsprotokoll für die Erweiterung auf Board-Ebene implementieren.

Erweiterte Daten für den Griff festlegen​

Unterstützte Datenlängen:

  • Upload (Client → Gerät) maximal 20 Byte.
  • Downlink (Gerät → Client) maximal 12 Byte, über Statusaktualisierungsnachrichten, um state.extension_data Zurück.

Datenspezifikationen:

  • Array-Länge:20 Byte
  • Wertebereich: Jeder Wert liegt zwischen 0 und 255
{
"wireless_verse_grip": [
{
"device_id": "049D",
"commands": {
"set_extension_data": {
"extension_data": [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
]
}
}
}
]
}

Beispiel​

Beispiel: Lastenverzeichnis der Erstausstattung​

Bei Herstellung einer WebSocket-Verbindung sendet der Dienst eine Nachricht mit der vollständigen Geräteliste. Die erste Nachricht hat folgenden Aufbau: JSON Format:

{
"inverse3": [
{
"device_id": "04BA",
"config": {
"type": "inverse3",
"port": "COM13",
"device_info": {
"major_version": 7,
"minor_version": 1,
"id": "04BA",
"device_type": 4,
"uuid": "2D35F80DD9005F599B68F49944CB04BA"
},
"extended_device_id": "2D35F80DD9005F599B68F49944CB04BA",
"extended_firmware_version": "8C20FDC8010AA1E15AA133CDA2534874",
"gravity_compensation": {
"enabled": true,
"scaling_factor": 1
},
"handedness": "right",
"streaming_mode": "USB",
"torque_scaling": {
"enabled": true
},
"home_return": {
"enabled": false
},
"filters": {
"force_gate": { "gain": 0.3 },
"damping": { "scalar": 0 }
},
"preset": "defaults",
"basis": { "permutation": "XYZ" },
"mount": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 1, "y": 1, "z": 1 }
}
},
"state": {
"cursor_position": {
"x": 0.07842738,
"y": -0.14836666,
"z": 0.14297646
},
"cursor_velocity": {
"x": -0.011969013,
"y": 0.0012009288,
"z": -0.043197
},
"angular_position": {
"x": -69.31704,
"y": 137.62952,
"z": 19.832787
},
"angular_velocity": {
"x": 0,
"y": 0,
"z": 0
},
"body_orientation": {
"x": -0.01940918,
"y": 0.7026367,
"z": 0.00048828125,
"w": 0.7113037
},
"current_cursor_force": { "x": 0, "y": 0, "z": 0 },
"current_cursor_position": { "x": 0, "y": 0, "z": 0 },
"current_angular_torques": { "x": 0, "y": 0, "z": 0 },
"current_angular_position": { "x": 0, "y": 0, "z": 0 },
"control_domain": "cartesian",
"control_mode": "force",
"transform": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 1, "y": 1, "z": 1 }
},
"transform_velocity": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 0, "y": 0, "z": 0 }
}
},
"status": {
"calibrated": false,
"in_use": false,
"power_supply": true,
"ready": true,
"started": true
}
}
],
"verse_grip": [
{
"device_id": "61548",
"config": {
"type": "verse_grip",
"port": "COM3",
"preset": "device_defaults",
"basis": { "permutation": "XYZ" },
"mount": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 1, "y": 1, "z": 1 }
}
},
"state": {
"button": false,
"hall": 0,
"orientation": {
"x": -0.5019531,
"y": 0.8632202,
"z": -0.048095703,
"w": -0.022338867
},
"transform": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 1, "y": 1, "z": 1 }
},
"transform_velocity": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 0, "y": 0, "z": 0 }
}
},
"status": {
"error": 0,
"ready": true
}
}
],
"wireless_verse_grip": [
{
"device_id": "0",
"config": {
"type": "wireless_verse_grip",
"port": "COM6",
"major_version": 1,
"minor_version": 4,
"hardware_version": 1,
"streaming_mode": "Radio",
"preset": "device_defaults",
"basis": { "permutation": "XYZ" },
"mount": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 1, "y": 1, "z": 1 }
}
},
"state": {
"battery_level": 0.816,
"battery_voltage": 3.77,
"buttons": {
"a": false,
"b": false,
"c": false
},
"hall": 16,
"orientation": {
"x": -0.019866943,
"y": -0.017486572,
"z": 0.05508423,
"w": -0.9963989
},
"transform": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 1, "y": 1, "z": 1 }
},
"transform_velocity": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 0, "y": 0, "z": 0 }
}
},
"status": {
"connected": true,
"awake": true,
"ready": true
}
}
]
}

Beispiel: Last zur Statusaktualisierung​

Bei jedem Eingang einer Nachricht sendet der Dienst eine Statusaktualisierung, die den Status aller Geräte enthält.

Wenn Sie den Status des Geräts ermitteln möchten, müssen Sie zuvor eine Nachricht an das Gerät senden (z. B. einen Abfragebefehl oder einen Kraftwert, auch wenn dieser Null ist). Dies ist besonders wichtig, wenn das Gerät als Eingangsquelle (z. B. zur Positionserfassung) verwendet wird und keine Kraft ausgeübt wird.

Statusaktualisierungen erfolgen wie folgt: JSON Format:

{
"inverse3": [
{
"device_id": "04BA",
"state": {
"cursor_position": {
"x": 0.07842738,
"y": -0.14836666,
"z": 0.14297646
},
"cursor_velocity": {
"x": -0.011969013,
"y": 0.0012009288,
"z": -0.043197
},
"angular_position": {
"x": -69.31704,
"y": 137.62952,
"z": 19.832787
},
"angular_velocity": {
"x": 0,
"y": 0,
"z": 0
},
"body_orientation": {
"x": -0.01940918,
"y": 0.7026367,
"z": 0.00048828125,
"w": 0.7113037
},
"current_cursor_force": { "x": 0, "y": 0, "z": 0 },
"current_cursor_position": { "x": 0, "y": 0, "z": 0 },
"current_angular_torques": { "x": 0, "y": 0, "z": 0 },
"current_angular_position": { "x": 0, "y": 0, "z": 0 },
"control_domain": "cartesian",
"control_mode": "force",
"transform": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 1, "y": 1, "z": 1 }
},
"transform_velocity": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 0, "y": 0, "z": 0 }
}
},
"status": {
"calibrated": false,
"in_use": false,
"power_supply": true,
"ready": true,
"started": true
}
}
],
"verse_grip": [
{
"device_id": "61548",
"state": {
"button": false,
"hall": 0,
"orientation": {
"x": -0.5019531,
"y": 0.8632202,
"z": -0.048095703,
"w": -0.022338867
},
"transform": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 1, "y": 1, "z": 1 }
},
"transform_velocity": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 0, "y": 0, "z": 0 }
}
},
"status": {
"error": 0,
"ready": true
}
}
],
"wireless_verse_grip": [
{
"device_id": "0",
"state": {
"battery_level": 0.816,
"battery_voltage": 3.77,
"buttons": {
"a": false,
"b": false,
"c": false
},
"hall": 16,
"orientation": {
"x": -0.019866943,
"y": -0.017486572,
"z": 0.05508423,
"w": -0.9963989
},
"transform": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 1, "y": 1, "z": 1 }
},
"transform_velocity": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 0, "y": 0, "z": 0 }
}
},
"status": {
"connected": true,
"awake": true,
"ready": true
}
}
],
"custom_verse_grip": [
{
"device_id": "0",
"state": {
"battery_level": 0.816,
"battery_voltage": 3.77,
"buttons": {
"a": false,
"b": false,
"c": false
},
"hall": 16,
"orientation": {
"x": -0.019866943,
"y": -0.017486572,
"z": 0.05508423,
"w": -0.9963989
},
"extension_data": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"transform": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 1, "y": 1, "z": 1 }
},
"transform_velocity": {
"position": { "x": 0, "y": 0, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"scale": { "x": 0, "y": 0, "z": 0 }
}
},
"status": {
"ready": true
}
}
]
}