Passer directement au contenu principal

Protocole WebSocket

Le canal de simulation est une connexion WebSocket surle port 10001. Il assure la transmission en temps réel des commandes et des boucles d'état entre l'application et le service.

Règle de base : une réponse par message​

Pour chaque message reçu d'un client, le service envoieexactement une mise à jour d'état:

Il n'y a ni interrogation, ni abonnement, ni notification « hors bande ». La fréquence des mises à jour dépend entièrement du débit d'envoi de l'application.


Étape 1 — Inventaire initial (premier message provenant du service)​

Lors de la connexion, le service, pour tous les appareils détectés,config,state,status y compris Un instantané complet Je vais envoyer :

{
"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": []
}

Les trois blocs sont mis à jour à des fréquences différentes :

BlocContenuFréquence des modifications
configInformations sur le micrologiciel, préréglages, basis, montage, filtresRarement modifié — Uniquement en cas de modification explicite des paramètres
statePosition, vitesse, force, posture, transformationÀ chaque tick (haute fréquence)
statusPrêt, calibré, sous tension, en cours d'utilisationDe temps en temps (peu fréquemment)

Étape 2 — Envoyer la première commande​

Il analyse l'inventaire initial pour identifier l'ID de l'appareil, puis renvoie un message contenant le profil de session, les paramètres de configuration initiaux (le cas échéant) et/ou des commandes de contrôle :

{
"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 } }
}
}
]
}

Étape 3 — Mise à jour de l'état à partir de cette étape​

Après les premiers échanges, le service ne déclenchera pas l'envoi d'un instantané complet, sauf si une modification des paramètres le provoque,state et status Je n'enverrai que cela (config (n'est pas inclus) :

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

Étape 4 — Répétition​

Lorsque vous envoyez une commande, vous recevez une mise à jour de l'état. La boucle se poursuit en fonction de la fréquence d'envoi.


configure et commands​

Chaque entrée de périphérique dans le message à envoyer peut contenir deux mappages.

CarteObjectifPermanence
configureParamètres à définir une seule fois : préréglages, références, montures, filtres, paramètres des modulesConserver jusqu'à modification
commandsContrôle pas à pas : force, position, coupleUne fois appliquée, elle est annulée

configure La liste complète des touches se trouve Paramètres de session ,commands En ce qui concerne les entrées Commandes de contrôle Veuillez consulter [...].

Remarque
set_transform C'est un cas particulier.

set_transform は commands qui se trouve en dessous, mais,Permanent. Le service conserve la dernière valeur jusqu'à ce qu'une nouvelle valeur soit envoyée. Cela s'explique par le fait que son objectif est la navigation dans la scène. On l'utilise lorsque l'on souhaite diffuser la transformation en continu pendant le déplacement de la caméra, tout en conservant la dernière position à chaque pression sur un bouton.


execute drapeau​

configure ou bien commands L'entrée contient "execute": false peut inclure. De ce fait, le service peut, sans appliquer de charge utile,Analyse et vérificationNous nous limitons à cela.

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

Cela affiche systématiquement tous les champs.Sérialiseur basé sur la réflexion(Exemple : Unity) JsonUtility) peut s'avérer utile. Pour les entrées inutilisées, execute: false Veuillez définir ce paramètre afin de ne pas écraser la configuration réelle. La valeur par défaut est true . Si l'on omet le drapeau, cela signifie « application normale ».


Avertissement​

Si vous avez déjà envoyé une commande, veuillez ne pas envoyer de requête.

probe_position et probe_orientation Il s'agit d'un « keep-alive » dédié à la surveillance, destiné aux sessions qui n'envoient pas de commandes de contrôle (par exemple : le hub «Haply »). Lorsque la session est déjà set_cursor_force,set_cursor_position Si vous envoyez, entre autres,Veuillez ne pas envoyer de sondes supplémentaires。L'état de l'appareil est déjà inclus dans toutes les réponses. Mélanger les deux revient à gaspiller de la bande passante, etsession-probe-dropped Un événement pourrait se produire.

Les clés inconnues seront ignorées sans avertissement.

Si la commande semble ne pas fonctionner, il se peut que le nom du champ soit incorrect. Le service ignore actuellement les clés JSON non reconnues sans générer d'erreur. Vérifiez les journaux du service et assurez-vous que le nom du champ correspond bien à celui indiqué dans la documentation de l'API. Ce comportement devrait être modifié dans les prochaines versions.