Protocole WebSocket
Le canal de simulation est une connexion WebSocket surle port 10001. Il assure la communication en temps réel entre votre application et le service, via un échange de commandes et d'états.
Règle fondamentale : chaque message correspond à une réponse
Le service envoie exactementune mise à jour d'étatpourchaque messagereçu du client :
Il n'y a ni interrogation, ni abonnement, ni notification hors canal. La fréquence des mises à jour dépend entièrement de votre cadence d'envoi.
Étape 1 — Liste initiale (premier message envoyé par le service)
Lors de la connexion, le service envoie un message à chaque appareil détectéInstantané complet, qui contient config,state et 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": []
}
La fréquence de mise à jour de ces trois blocs de données varie :
| Bloc de données | Contenu | Fréquence des modifications |
|---|---|---|
config | Informations sur le micrologiciel, préréglages, base, montage, filtres | Très rarement — uniquement lorsque la configuration est explicitement modifiée |
state | Position, vitesse, force, orientation, transformation | À chaque tick (haute fréquence) |
status | Prêt, calibré, sous tension, en cours d'utilisation | De temps en temps (rarement) |
Étape 2 — Envoyer la première commande
Analysez la liste initiale pour trouver l'identifiant de votre appareil, puis renvoyez un message contenant la configuration de votre session, ainsi que toute configuration initiale et/ou commande 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 — Mises à jour ultérieures sur l'état d'avancement
Après la première interaction, à moins qu'une modification de la configuration ne déclenche l'envoi d'un instantané complet, le service n'enverra que state + status(hors config) :
{
"session_id": 7,
"inverse3": [
{
"device_id": "049D",
"state": { "cursor_position": { … }, "cursor_velocity": { … }, … },
"status": { "ready": true, "calibrated": true, … }
}
]
}
Étape 4 — Répéter
Envoyer une commande → Recevoir une mise à jour d'état. Le cycle se poursuit à votre rythme d'envoi.
configure et commands
Dans les messages que vous envoyez, chaque entrée d'appareil peut contenir deux mappages :
| Mappage | Utilisation | Persistance |
|---|---|---|
configure | Paramètres à définir une seule fois : préréglages, base, montage, filtres, configuration des modules | Reste en vigueur jusqu'à ce qu'il soit modifié |
commands | Contrôle cycle par cycle : force, position, couples | À utiliser une seule fois ; après quoi elle perdra son efficacité. |
À propos de configure Pour consulter la liste complète des touches, voir Configuration de la session; À propos de commands Pour plus d'informations sur cet article, veuillez consulter Commandes de contrôle。
set_transform C'est un cas particulier.set_transform Situé à commands ci-dessous, mais c'estla persistance——Le service conserve la dernière valeur jusqu’à ce que vous envoyiez une nouvelle valeur. En effet, il est utilisé pour la navigation dans les scènes : vous envoyez les transformations en continu lorsque la caméra se déplace, mais vous souhaitez conserver la dernière position entre deux pressions sur une touche.
execute Logo
N'importe quel configure ou commands Les entrées peuvent toutes contenir "execute": false, afin que le serviceAnalyse et vérificationCharger sans l'appliquer.
{
"inverse3": [{
"device_id": "049D",
"configure": {
"preset": { "preset": "arm_front", "execute": true },
"damping": { "scalar": 0.0, "execute": false }
}
}]
}
Cela concerneSérialiseur basé sur la réflexion(par exemple, Unity) JsonUtility) très utile, ce type de sérialiseur affiche toujours tous les champs : il suffit de définir les entrées inutilisées comme execute: false, afin qu’elles ne remplaient pas la configuration réelle. La valeur par défaut est true——L'absence de ce symbole signifie que l'application fonctionne normalement.
Avertissement
probe_position et probe_orientation Il s'agit simplement d'un message de maintien de connexion à des fins de surveillance, destiné aux sessions qui n'envoient pas de commandes de contrôle (par exemple, Haply Hub). Si votre session envoie déjà des set_cursor_force,set_cursor_position etc.,Veuillez ne plus envoyer de messages de test simultanément.——L'état de l'équipement est déjà inclus dans chaque réponse. Leur utilisation simultanée entraînerait un gaspillage de bande passante et pourrait également déclencher session-probe-dropped Incident.
Si une commande semble ne produire aucun effet, il est fort probable que le nom du champ soit incorrect. Le service ignore actuellement les clés JSON non reconnues sans générer d'erreur. Veuillez consulter les journaux du service et vérifier le nom du champ en vous référant à la documentation de l'API. Ce comportement devrait être modifié dans les prochaines versions.