Skip to main content
Version : 3.5.x

Canal de simulation

Vue d'ensemble

Le canal de simulation est un canal WebSocket bidirectionnel à haute fréquence utilisé pour échanger des informations sur l'état des appareils et envoyer des commandes de session ou des commandes aux appareils.

URL par défaut : ws://localhost:10001

Le port peut être modifié dans la configuration.

Contrat principal (important) :

  • Lorsqu'un client se connecte, le service envoie un message d'inventaire initial contenant la liste complète des appareils.
  • Ensuite, le serveur envoie exactement un message de mise à jour d'état pour chaque message reçu du client.
  • Chaque rapport d'état contient l'état (et le statut) de tous les appareils.

:::info Modules Cette page présente le protocole et les commandes de base du canal de simulation.

Des modules ou fonctionnalités supplémentaires peuvent s'enregistrer et étendre le système avec leurs propres commandes et/ou champs d'état. Ceux-ci sont documentés séparément dans la section « Modules ». :::

Règles de protocole

Une réponse par message client

Le service envoie un message « State Update » contenant l'état de tous les appareils pour chaque message reçu du client.

Cela signifie :

  • Si vous avez besoin d'un instantané récent de l'état de l'appareil, vous devez envoyer une commande (une commande de session, une commande de sondage ou une commande de périphérique).
  • Le canal fonctionne comme une boucle « tick » déclenchée par les messages du client.

Interrogation sans application de forces (commandes de sondage)

Si vous souhaitez observer les changements d'état sans appliquer de forces ni modifier les paramètres de simulation, utilisez les commandes de sondage :

  • probe_position pour inverse3
  • probe_orientation pour les poignées Verse

Les commandes de sondage ne contiennent aucune donnée de commande et se contentent de déclencher des requêtes d'informations sur l'appareil, afin que les données de position et d'orientation soient à jour lors de la prochaine mise à jour d'état.

Configuration vs état

  • Les Inventaire initial le message inclut l'appareil config, stateet status.
  • Régulier Le point sur la situation les messages incluent l'appareil state et status.

Si vous avez à nouveau besoin d'un instantané incluant la configuration, utilisez session.force_render_full_state.

Systèmes de coordonnées

Haply par défaut un système de coordonnées droitier avec l'axe Z vers le haut.

Deux paramètres de session influent sur la manière dont les coordonnées sont interprétées et renvoyées :

Formats de messages

Cette section décrit les grandes lignes des types d'enveloppes et de messages. Des exemples complets sont fournis plus loin dans ce document.

Groupes de périphériques

Les messages sont regroupés par type d'appareil au niveau supérieur (par exemple inverse3, verse_grip, wireless_verse_grip). Chaque clé de type d'appareil correspond à un tableau d'objets spécifiques à chaque appareil.

Inventaire initial (serveur → client)

Envoyé immédiatement après l'établissement d'une connexion WebSocket.

Chaque entrée comprend :

  • device_id
  • config
  • state
  • status

Voir : Exemple : Charge utile de l'inventaire initial

Mise à jour de l'état (serveur → client)

Envoyé une fois pour chaque message client.

Chaque entrée comprend :

  • device_id
  • state
  • status

Voir : Exemple : Charge utile de mise à jour d'état

Enveloppe de commande de session (client → serveur)

Les commandes de session sont des actions qui s'appliquent à la connexion ou à la session en cours et ne sont pas spécifiques à un périphérique.

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

Enveloppe de commande de périphérique (client → serveur)

Les commandes destinées aux périphériques sont envoyées sous la clé du type de périphérique sous forme de tableau, ce qui permet d'envoyer des commandes à un ou plusieurs périphériques dans un seul message.

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

Vous pouvez inclure plusieurs entrées dans un même message afin de commander plusieurs appareils du même type. Notez que commands Il s'agit d'un dictionnaire capable de gérer plusieurs commandes pour un périphérique donné, mais une seule par type de commande.


Référence des commandes

Session

Forcer le rendu de l'état complet

Demandez un aperçu de tous les états et configurations des appareils.

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

Définir l'origine des coordonnées

Définir l'origine des coordonnées pour tous les appareils.

{
"session": {
"set_coordinate_origin": {
"coordinate_origin": "workspace_center"
}
}
}

Valeurs prises en charge :

  • device_base (par défaut)
  • workspace_center

Si vous définissez l'origine sur workspace_center, le (0, 0, 0) La position est déplacée au centre de l'espace de travail de l'appareil, qui varie en fonction du type d'appareil.

Base fixe

Définissez le mappage de base pour la session en cours. Le mappage de base définit la transformation du système de coordonnées Haplyvers le vôtre pour toute la durée de la session.

Après avoir posé les bases :

  • Tous les états renvoyés par le système sont représentés dans cette base.
  • Toutes les valeurs que vous envoyez dans le cadre d'autres commandes sont interprétées selon ce principe.

La mise en correspondance est définie par rapport aux Haply et s'exprime sous la forme d'une permutation de X, Y, Z, éventuellement précédé de + ou -. Exemples de valeurs valides :

  • XYZ, ZYX
  • +Y-Z+X, X-ZY

Exemple d'interprétation :

  • YZX signifie Y a raison, Z est en avant, X est en ligne.

Exemple d'un système de défilement vertical à gauche comme dans Unreal (X-YZ) :

{
"session": {
"set_basis": {
"basis": {
"permutation": "X-YZ"
}
}
}
}

Toutes les commandes des appareils

Test (tous les appareils)

Utilisez des commandes de sondage pour obtenir des informations actualisées sur la position et l'orientation sans appliquer de forces ni apporter d'autres modifications à la simulation.

  • inverse3: probe_position
  • Poignées Verse (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": {}
}
}
]
}

Inverse3

Pour envoyer des commandes à un inverse3 appareil, inclure une entrée correspondant à device_id sous le inverse3 clé.

Commander un appareil :

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

Commandez plusieurs appareils en un seul message :

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

Définir la position du curseur

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

Définir la force du curseur

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

Définir la position angulaire

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

Réglage du couple angulaire

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

Poignée Verse prolongée

Les set_extension_data Cette commande fait partie du protocole étendu pour les poignées Verse ; elle est utilisée avec les versions de poignées qui prennent en charge le protocole de communication d'extension de la carte.

Données sur l'extension de la poignée

Longueurs de données prises en charge :

  • Jusqu'à 20 octets en amont (client → appareil).
  • Jusqu'à 12 octets en sortie (appareil → client), renvoyés dans le message « State Update » sous la forme state.extension_data.

Spécifications des données :

  • Longueur du tableau : 20 octets
  • Plage de valeurs : chaque valeur est comprise entre 0 et 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
]
}
}
}
]
}

Exemples

Charge utile initiale

Le service envoie un message contenant la liste complète des appareils lorsqu'une connexion WebSocket est établie. Le message initial contient les éléments suivants : JSON format :

{
"inverse3": [
{
"device_id": "04BA",
"config": {
"type": "inverse3",
"device_info": {
"minor_version": 1,
"major_version": 7,
"id": "04BA",
"model": 4,
"uuid": "2D35F80DD9005F599B68F49944CB04BA"
},
"port": "COM13",
"extended_device_id": "2D35F80DD9005F599B68F49944CB04BA",
"extended_firmware_version": "8C20FDC8010AA1E15AA133CDA2534874",
"gravity_compensation": {
"enabled": true,
"scaling_factor": 1
},
"handedness": "right",
"torque_scaling": {
"enabled": true
}
},
"state": {
"angular_position": {
"a0": -69.31704,
"a1": 137.62952,
"a2": 19.832787
},
"angular_velocity": {
"a0": 0,
"a1": 0,
"a2": 0
},
"body_orientation": {
"x": -0.01940918,
"y": 0.7026367,
"z": 0.00048828125,
"w": 0.7113037
},
"cursor_position": {
"x": 0.07842738,
"y": -0.14836666,
"z": 0.14297646
},
"cursor_velocity": {
"x": -0.011969013,
"y": 0.0012009288,
"z": -0.043197
},
"mode": "idle"
},
"status": {
"calibrated": false,
"in_use": false,
"power_supply": true,
"ready": true,
"started": true
}
}
],
"verse_grip": [
{
"device_id": "61548",
"config": {
"port": "COM3",
"type": "verse_grip"
},
"state": {
"button": false,
"hall": 0,
"orientation": {
"x": -0.5019531,
"y": 0.8632202,
"z": -0.048095703,
"w": -0.022338867
}
},
"status": {
"error": 0,
"ready": true
}
}
],
"wireless_verse_grip": [
{
"device_id": "0",
"config": {
"port": "COM6",
"type": "wireless_verse_grip",
"major_version": 1,
"minor_version": 4,
"hardware_version": 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
}
},
"status": {
"connected": true,
"awake": true,
"ready": true
}
}
]
}

Mise à jour de l'état de la charge utile

Pour chaque message reçu, le service enverra un message de mise à jour de l'état contenant l'état de tous les appareils.

Si vous souhaitez connaître l'état de la machine, vous devez lui envoyer un message au préalable (par exemple, une commande de sondage ou une valeur de force, même si ces valeurs sont égales à zéro). Ceci est particulièrement important lorsque vous utilisez des dispositifs comme sources d'entrée (par exemple, la position de suivi) sans appliquer de forces.

Le message de mise à jour de l'état contient les informations suivantes JSON format :

{
"inverse3": [
{
"device_id": "04BA",
"state": {
"angular_position": {
"a0": -69.31704,
"a1": 137.62952,
"a2": 19.832787
},
"angular_velocity": {
"a0": 0,
"a1": 0,
"a2": 0
},
"body_orientation": {
"x": -0.01940918,
"y": 0.7026367,
"z": 0.00048828125,
"w": 0.7113037
},
"cursor_position": {
"x": 0.07842738,
"y": -0.14836666,
"z": 0.14297646
},
"cursor_velocity": {
"x": -0.011969013,
"y": 0.0012009288,
"z": -0.043197
},
"mode": "idle"
},
"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
}
},
"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
}
},
"status": {
"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]
},
"status": {
"ready": true
}
}
]
}