Aller au contenu principal

09. Navigateur d'espace de travail WebSocket

Naviguez la position de l'espace de travail de l'appareil en temps réel en envoyant en continu des commandes set_transform sur le canal WebSocket. Le tutoriel utilise HTTP pour découvrir la session et l'appareil (exactement comme le tutoriel 08), puis ouvre une liaison WebSocket pour transmettre les mises à jour de position à chaque cycle.

Cela illustre la différence entre deux opérations de transformation :

OpérationTutorielUsage typique
configure.mount — transformation de montage persistante08Définie une seule fois (ou rarement) pour décrire le montage physique de l'appareil
set_transform — transformation persistante de l'espace de travail09 (ce tutoriel)Également persistante, mais peut être transmise en continu à chaque cycle pour une navigation en temps réel dans l'espace de travail

Les deux commandes sont disponibles via HTTP et WebSocket, et toutes deux sont persistantes : le service mémorise la dernière valeur que vous avez envoyée. La différence tient à l'objectif et à la fréquence de mise à jour : configure.mount est optimisée pour des mises à jour peu fréquentes (installation physique), tandis que set_transform est optimisée pour une transmission en continu à haute fréquence (navigation dans la scène).

Utilisez set_transform lorsque l'origine de l'espace de travail doit suivre quelque chose qui change à l'exécution : suivre une main, animer un décalage procédural ou permettre à un opérateur de déplacer l'espace de travail virtuel en direct.

Le montage et l'espace de travail sont imbriqués

Pris séparément, configure.mount et set_transform semblent produire le même effet, mais ils sont imbriqués : dans le pipeline de coordonnées, la transformation de l'espace de travail est appliquée par-dessus le montage (device → basis → mount → workspace → application). Voir Montage et espace de travail pour le pipeline complet.

Cas d'utilisation​

  • Navigation en direct dans l'espace de travail. Déplacez l'espace de travail du curseur de l'appareil (la région délimitée qu'atteint l'effecteur) sans interrompre la scène haptique.
  • Alignement piloté par un opérateur. Laissez quelqu'un, dans un second terminal, maintenir les touches fléchées pour décaler l'espace de travail pendant que l'application haptique principale fonctionne — utile pour l'étalonnage au poste de travail pendant une session en direct.
  • Déplacement procédural de l'espace de travail. Pilotez la position de l'espace de travail à partir d'un script (réactif à l'audio, piloté par la physique, etc.) en envoyant à chaque cycle des correctifs de transformation ne portant que sur la position.

Prérequis​

Le tutoriel 09 nécessite une session WebSocket active — un client qui dispose déjà de Inverse3 dans une boucle haptique en cours d'exécution. Le tutoriel 09 se rattache ensuite à cette session et décale son espace de travail en direct.

Le moyen le plus rapide de lancer une session

Ouvrez Haply Hub et lancez la démo Orb. Elle ouvre une session haptique persistante que vous pouvez cibler immédiatement :

./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 à l'origine de l'espace de travail — déplacer l'espace de travail avec le tutoriel 09 décale toute la scène en temps réel, ce qui vous donne un retour visuel instantané.

Tout autre tutoriel (01 à 07) qui exécute une boucle haptique fonctionne également. Lancez-le dans un premier terminal, puis démarrez le tutoriel 09 dans un second terminal et laissez-le découvrir la session de manière interactive.

Utilisation​

# 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

Commandes​

Maintenez une touche enfoncée pour un déplacement continu. Relâchez pour arrêter.

ToucheAction
→ / ←+X / −X
↑ / ↓+Y / −Y
Page Up / Page Down+Z / −Z
= / -Augmenter / diminuer la vitesse de navigation
0Réinitialiser l'espace de travail à l'origine
HAfficher l'aide
EscQuitter (Ctrl+C fonctionne aussi)

Fonctionnement​

Étape 1 — HTTP : découverte de la session et de l'appareil​

Le tutoriel réutilise les mêmes fonctions utilitaires discover_session() / discover_device() que le tutoriel 08 : GET /sessions (ou GET /sessions/<selector> avec --session), puis GET /devices (ou utilisation directe de --device). Les deux fonctions acceptent les mêmes options CLI, avec un texte SESSION_HELP identique : un sélecteur issu du tutoriel 00 ou 08 fonctionne ici sans modification.

Étape 2 — WebSocket session, négociation au premier message​

Le tutoriel ouvre une WebSocket vers ws://localhost:10001. Au premier message reçu seulement, il envoie l'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}}}}}]
}

Les ticks suivants omettent session — seul le tableau de commandes inverse3 est envoyé.

Étape 3 — set_transform à chaque tick​

set_transform accepte une transformation partielle — seulement les champs que vous souhaitez modifier. Ce tutoriel n'envoie que la position ; la rotation et l'échelle restent à leurs valeurs de session par défaut (celles définies par configure.mount, le cas échéant).

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

La position s'accumule tick par tick. À environ 1 kHz, le service réapplique set_transform à chaque tick (maintien d'ordre zéro), de sorte que l'espace de travail reste à la dernière position envoyée.

set_transform ou configure.mount

Les deux commandes enregistrent une transformation persistante par session, mais la transformation de l'espace de travail se place par-dessus le montage dans le pipeline (voir Montage et espace de travail). Pendant que le tutoriel 09 diffuse set_transform à chaque tick, chaque nouvelle trame WebSocket remplace la transformation d'espace de travail diffusée précédemment ; ainsi, tout autre client qui diffuse set_transform vers le même appareil sera écrasé au tick suivant. configure.mount est indépendant et conserve sa valeur. En pratique, choisissez un canal par préoccupation : le montage pour la configuration physique, set_transform pour la navigation en direct.

Modèle de threads (C++)​

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

ThreadRôle
Thread principalLit std::getline(std::cin, ...), analyse les jetons, met à jour nav_vel[] et default_step
Thread de rappel WebSocketFait avancer nav_pos[] avec nav_vel[] * dt, sérialise set_transform et l'envoie

std::mutex nav_mutex protège nav_pos[], nav_vel[] et default_step. L'horodatage last_tick et l'indicateur first_ws_msg sont locaux au rappel WS et n'ont pas besoin de mutex.

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
};

Source​

Livré avec le programme d'installation du SDK

Le tutoriel 09 est installé localement avec le SDK — consultez tutorials/09-haply-inverse-ws-remote-control/ dans le répertoire d'installation du service.

Voir aussi : commande set_transform · Sessions — négociation au premier message · Montage et espace de travail · Sélecteurs · Tutoriel 08 — HTTP Configuration à distance · Tutoriel 07 — Base et montage