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 :
| Bloc | Contenu | Fréquence des modifications |
|---|---|---|
config | Informations sur le micrologiciel, préréglages, basis, montage, filtres | Rarement modifié — Uniquement en cas de modification explicite des paramètres |
state | Position, vitesse, force, posture, transformation | À chaque tick (haute fréquence) |
status | Prêt, calibré, sous tension, en cours d'utilisation | De 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.
| Carte | Objectif | Permanence |
|---|---|---|
configure | Paramètres à définir une seule fois : préréglages, références, montures, filtres, paramètres des modules | Conserver jusqu'à modification |
commands | Contrôle pas à pas : force, position, couple | Une 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 [...].
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
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.
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.