Aller directement au corps du texte

09. Navigateur d'espaces de travail WebSocket

set_transform En diffusant les commandes via un canal WebSocket, les appareils Localisation de l'espace de travail en temps réel Exploration. Ce tutoriel explique comment explorer les sessions et les appareils via HTTP (Tutoriel n° 08(exactement de la même manière), puis ouvre une connexion WebSocket afin d'envoyer une mise à jour de position à chaque tick.

Ce tableau illustre la différence entre deux opérations de conversion :

OpérationTutorielUtilisations courantes
configure.mount — Conversion des montures permanentes08Configuration effectuée une seule fois (ou rarement) pour décrire le montage physique de l'appareil
set_transform — Conversion en espace de travail permanent09 (ce tutoriel)Bien qu'il s'agisse là encore d'une solution permanente, il est possible de diffuser en continu à chaque tick pour permettre l'exploration de l'espace de travail en temps réel.

Ces deux commandes HTTP et WebSocket Ils peuvent être utilisés dans cet environnement, et les deux permanentEn effet, le service mémorise la dernière valeur envoyée. La différence entre ces deux commandes réside dans leur objectif et leur fréquence de mise à jour. configure.mountest optimisé pour les mises à jour peu fréquentes (paramètres physiques), tandis que, set_transformIl est optimisé pour le streaming à haute fréquence (navigation entre les scènes).

Lorsqu'il faut suivre des objets dont le point d'origine de l'espace de travail change pendant l'exécution set_transformUtilisez-le. Par exemple, pour suivre le mouvement de la main, mettre en œuvre une animation avec un décalage procédural ou permettre à l'opérateur d'ajuster finement l'espace de travail virtuel en temps réel.

Les montages et les espaces de travail sont liés par une relation parent-enfant.

Si l'on considère chaque cas individuellement, configure.mountWa set_transformBien que cela semble produire le même effet, ces deux valeurs sont Relations parents-enfantsC'est le pipeline de coordonnées (device → basis → mount → workspace → application) La conversion de l'espace de travail s'effectue lors du montage ci-dessus S'applique. L'ensemble du pipeline est Montage et espace de travailVeuillez consulter [...].

Cas d'utilisation​

  • Navigation en temps réel dans l'espace de travail. Déplacez le curseur de l'espace de travail de l'appareil (zone limite accessible par l'effecteur terminal) sans interrompre la scène haptique.
  • Alignement piloté par l'opérateur. Permet à un autre utilisateur, depuis un deuxième terminal, de déplacer l'espace de travail à l'aide des touches directionnelles pendant que l'application haptique principale est en cours d'exécution. Utile pour l'étalonnage des plans de travail par utilisateur lors d'une session en direct.
  • Mouvement procédural de l'espace de travail. À chaque tick, un patch de transformation dédié à la position est envoyé afin de piloter la position de l'espace de travail via des scripts (réactifs à l'audio, basés sur la physique, etc.).

Conditions préalables​

Le tutoriel 09 nécessite une session WebSocket active. Cela signifie que vous devez être un client utilisant Inverse3 dans une boucle haptique déjà en cours d'exécution. Le tutoriel 09 se connecte à cette session, puis déplace l'espace de travail en temps réel.

Comment exécuter une session le plus rapidement possible

Haply OuvrezHubet lancez la démo Orb. Une session haptique permanente s'ouvrira alors, que vous pourrez immédiatement cibler :

./09-haply-inverse-ws-remote-control --session co.haply.hub::demo-orb
python 09-haply-inverse-ws-remote-control.py --session "co.haply.hub::demo-orb"

La scène « Orb » affiche une sphère au point d'origine de l'espace de travail. Lorsque vous vous déplacez dans l'espace de travail à l'aide du tutoriel 09, la scène entière se déplace en temps réel, offrant ainsi un retour visuel immédiat.

Les autres tutoriels (01 à 07) qui utilisent Haptic Loop fonctionnent également tous. Lancez ces tutoriels dans un terminal, puis exécutez le tutoriel 09 dans un deuxième terminal pour explorer la session de manière interactive.

Mode d'emploi​

# Discover session interactively, use first detected device
./09-haply-inverse-ws-remote-control
python 09-haply-inverse-ws-remote-control.py

# Target the Haply Hub Orb demo directly
./09-haply-inverse-ws-remote-control --session co.haply.hub::demo-orb
python 09-haply-inverse-ws-remote-control.py --session "co.haply.hub::demo-orb"

# Target a session directly, specify device
./09-haply-inverse-ws-remote-control --session :my_profile:0 --device A14
python 09-haply-inverse-ws-remote-control.py --session "#42" --device A14

Mode d'emploi​

Si vous maintenez la touche enfoncée, vous avancez en continu. Lorsque vous relâchez la touche, vous vous arrêtez.

cléMouvement
→ / ←+X / −X
↑ / ↓+Y / −Y
Page Up / Page Down+Z / −Z
= / -Augmenter / réduire la vitesse de navigation
0Réinitialiser l'espace de travail à son état d'origine
HAfficher l'aide
EscFin (Ctrl+C(fonctionne également)

Principe de fonctionnement​

Étape 1 — Sessions HTTP et identification des appareils​

Ce tutoriel est Tutoriel n° 08identique à discover_session() / discover_device() Réutilisation des helpers. GET /sessions(ou --sessionà utiliser avec GET /sessions/<selector>) puis, GET /devicesen appelant ou --deviceles utilise directement. Les deux fonctions d'aide ont la même SESSION_HELP Il accepte les mêmes options CLI que le texte, et les sélecteurs des tutoriels 00 ou 08 fonctionnent ici également sans modification.

Étape 2 — Session WebSocket, échange de messages d'établissement de connexion​

Ce tutoriel est ws://localhost:10001Ouvre une connexion WebSocket. Uniquement pour le premier message reçu Envoi des informations d'enregistrement du profil de session :

{
"session": {"configure": {"profile": {"name": "co.haply.inverse.tutorials:ws-remote-control"}}},
"inverse3": [{"device_id": "...", "commands": {"set_transform": {"transform": {"position": {"x": 0, "y": 0, "z": 0}}}}}]
}

Par la suite, sur Tick : sessionen omettant, inverse3 Seuls les tableaux de commandes sont transmis.

Étape 3 — À chaque tic set_transform Exécution​

set_transform은 Conversion partielleest autorisé. En d’autres termes, il suffit de spécifier uniquement les champs que vous souhaitez modifier. Ce tutoriel ne transmet que la position ; la rotation et la mise à l’échelle utilisent les valeurs par défaut de la session (si elles ont été définies) configure.mount (valeur spécifiée par la commande) est conservée telle quelle.

{
"inverse3": [{"device_id": "...", "commands": {"set_transform": {"transform": {"position": {"x": 0.02, "y": 0.0, "z": 0.01}}}}}]
}

La position est cumulée à chaque tick. À environ 1 kHz, le service enregistre à chaque tick set_transformest réappliqué (maintien « zero-order »). L'espace de travail reste donc exactement à la position où il a été transmis en dernier.

set_transformet configure.mountLa différence entre

Ces deux commandes enregistrent les conversions de manière permanente par session, mais dans le pipeline, la conversion de l'espace de travail est montée ci-dessus est placé (Montage et espace de travail (voir). Le tutoriel n° 09 à chaque tick set_transformPendant la diffusion en continu, chaque fois qu’une nouvelle trame WebSocket arrive, la transformation de l’espace de travail diffusée précédemment est remplacée. Par conséquent, sur le même appareil, set_transformLes autres clients diffusant ce flux seront écrasés au prochain tick. configure.mountest indépendant et conserve sa propre valeur. En pratique, choisissez un canal par sujet d'intérêt. Pour les réglages physiques, utilisez « mount » ; pour la navigation en temps réel, utilisez set_transformutilise.

Modèle de threading (C++)​

Le tutoriel C++ utilise deux threads qui partagent un compteur de position :

Fil de discussionRôle
Fil principalLecture de l'entrée (std::getline(std::cin, ...)), analyse syntaxique des jetons, nav_vel[] et default_step Mise à jour
Fil de rappel WebSocketnav_vel[] * dt en utilisant la valeur nav_pos[]et faire progresser, set_transformen le sérialisant puis en le transmettant

std::mutex nav_mutexest nav_pos[], nav_vel[], default_steple protège. last_tick l'horodatage et first_ws_msg Le drapeau étant une variable locale limitée au callback WS, aucun mutex n'est nécessaire.

ws.onmessage = [&](const std::string &) {
float pos_snap[3];
{
std::lock_guard<std::mutex> lk(nav_mutex);
for (int i = 0; i < 3; ++i) nav_pos[i] += nav_vel[i] * 0.001f; // mm/frame → m
for (int i = 0; i < 3; ++i) pos_snap[i] = nav_pos[i];
}
// build and send set_transform with pos_snap
};

Code source​

Fourni avec le programme d'installation du SDK

Le tutoriel 09 est installé localement avec le SDK. Dans le répertoire d'installation du service, sous tutorials/09-haply-inverse-ws-remote-control/Veuillez consulter cette page.

Documents connexes : set_transform commande · Session — Échange de messages d'établissement de connexion · Montage et espace de travail · Sélecteur · Tutoriel 08 — Configuration à distance via HTTP · Tutoriel 07 — Basis et montage