Aller directement au corps du texte

01. Sortie « Inverse3 »

En se connectant au WebSocket de simulation, on diffuse en continu la position du curseur, la vitesse et la force du premier Inverse3 signalées par le service.

Contenu pédagogique :

  • Ouvrir une connexion WebSocket et recevoir le message d'état initial complet
  • Aucun effort pour maintenir la session active set_cursor_force Envoyer un « Keep Alive »
  • Haply Enregistrer un profil de session pour permettre au Hub de reconnaître la simulation
  • Modèle de « handshake » exécuté uniquement lors du premier message — Suppression de « session/configure » après la première transmission
  • Espace de travail avec mise à jour partielle sémantique transformLecture (position, rotation, échelle)
  • Réguler le débit de sortie de la console à une vitesse de lecture confortable

Flux de travail​

  1. ws://localhost:10001Ouvre une connexion WebSocket. Le service affiche la liste des appareils connectés. Trame d'état complèteest envoyé immédiatement.
  2. Dans la première image, le premier Inverse3 de device_idSélectionnez cette option, puis créez un message de requête composé de deux parties :
    • session.configure.profile.name — Hub HaplyEnregistrez la simulation.
    • Par appareil, à l'aide du vecteur zéro set_cursor_force Commande. Le service l'utilise comme mécanisme de maintien de connexion et continue d'envoyer des trames d'état tant que des commandes continuent d'arriver.
  3. Le message est renvoyé. Avant le prochain tick, session Supprimer le champ — Le profil de session correspondant à une poignée de main unique ; par conséquent, lors des ticks suivants, seules les commandes sont transmises.
  4. Par la suite, à chaque image d'état, le curseur vec3 Les données de champ (position, vitesse, force) sont transmises à une fréquence d'environ 10 Hz, et un signal de maintien à force nulle est à nouveau envoyé.

Paramètres​

NomValeur par défautUtilisation
URIws://localhost:10001URL WebSocket du canal de simulation
PRINT_EVERY_MS100Limitation de la sortie de la console
Nom du profil de sessionco.haply.inverse.tutorials:print-inverse3Haply Identifier cette simulation dans Hub

Champ « État de lecture »​

data.inverse3[0].stateOn peut y lire ce qui suit :

  • cursor_position, cursor_velocity, current_cursor_force — respectivement vec3
  • transform — Sous-objet de conversion d'espace de travail. position(vec3), rotation(quaternion), scale(vec3) contient ce champ.
Sémantique des mises à jour partielles

les sous-champs dont la valeur par défaut est identique à celle de l'élément de base (position: {0,0,0}, rotation: {w:1,x:0,y:0,z:0}, scale: {1,1,1}) supprime, dans la charge utile, afin d'économiser de la bande passante, (omission). Veillez à toujours spécifier une valeur par défaut lors de la lecture d'une valeur (par exemple, en C++ : .value("position", default_pos), en Python .get("position", default_pos)). Pour toujours recevoir tous les champs, serialization/explicit_fieldsVeuillez l'activer.

Émission / Réception​

Boucle WebSocket : réception d'une trame d'état, Cadre de commandeet la retransmet. La première trame de commande contient la négociation de session et une puissance nulle set_cursor_force Il inclut la fonction « Keep-Alive », et toutes les trames suivantes contiennent Uniquement KeepAlive est inclus (la session est supprimée).

Boucle asynchrone unique — recv() → Créer une commande → send() → Répéter.

async with websockets.connect(URI) as websocket:
while True:
msg = await websocket.recv()
data = json.loads(msg)

if first_message:
first_message = False
device_id = data["inverse3"][0]["device_id"]
request_msg = {
"session": {"configure": {"profile": {
"name": "co.haply.inverse.tutorials:print-inverse3"}}},
"inverse3": [{
"device_id": device_id,
"commands": {"set_cursor_force":
{"vector": {"x": 0.0, "y": 0.0, "z": 0.0}}},
}]
}

await websocket.send(json.dumps(request_msg))
request_msg.pop("session", None) # one-shot handshake

Options de ligne de commande (Python)​

La variante Python prend en charge deux indicateurs permettant de modifier la sortie du tutoriel :

drapeauEffet
--fullAu lieu d'un résumé en une ligne, cette commande affiche de manière claire le contenu JSON brut de toutes les trames d'état. Elle est utile pour vérifier quels champs sont exportés par le service.
--query-configÀ chaque tick sortant session.force_render_full_state: {}en le réinjectant, afin que le service soit présent à chaque trame config Permet de réexporter un instantané complet, y compris les blocs (type de périphérique, micrologiciel, préréglages, montage, filtres, etc.). Si cet indicateur n'est pas spécifié, confign'est transmis que dans la première image ; les images suivantes sont des images delta de streaming.

Ces deux indicateurs peuvent être utilisés conjointement — python 01-haply-inverse-print-inverse3.py --full --query-configLorsque vous l'exécutez, à chaque tick, configLa charge utile JSON complète indiquée s'affiche. Cela s'avère utile pour observer les modifications en temps réel des paramètres via l'Haply Hub ou l'API HTTP. La commande WebSocket sous-jacente est la suivante : session.force_render_full_stateVeuillez consulter [...].

La variante C++ ne propose pas cette option : elle n'affiche toujours qu'un résumé d'une ligne, et confign'est reçu que dans la première image.

Fourni avec le programme d'installation du SDK

Le tutoriel 01 est également installé localement avec le SDK — dans le répertoire d'installation du service, sous tutorials/01-haply-inverse-print-inverse3/Vous pouvez le consulter ici.

Source : Python · C++ · C++ Glaze

À ce sujet : Protocole WebSocket · Commandes de contrôle (set_cursor_force) · session · Type (vec3)