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ération | Tutoriel | Usage typique |
|---|---|---|
configure.mount — transformation de montage persistante | 08 | Définie une seule fois (ou rarement) pour décrire le montage physique de l'appareil |
set_transform — transformation persistante de l'espace de travail | 09 (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.
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.
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
- Python
- C++
Maintenez une touche enfoncée pour un déplacement continu. Relâchez pour arrêter.
| Touche | Action |
|---|---|
→ / ← | +X / −X |
↑ / ↓ | +Y / −Y |
Page Up / Page Down | +Z / −Z |
= / - | Augmenter / diminuer la vitesse de navigation |
0 | Réinitialiser l'espace de travail à l'origine |
H | Afficher l'aide |
Esc | Quitter (Ctrl+C fonctionne aussi) |
Par lignes : saisissez la commande, puis appuyez sur ENTRÉE.
| Commande | Action |
|---|---|
x+[N] / x-[N] | Régler la vitesse X à ±N mm/trame (x+ seul utilise la vitesse par défaut actuelle) |
y+[N] / y-[N] | Régler la vitesse Y à ±N mm/trame |
z+[N] / z-[N] | Régler la vitesse Z à ±N mm/trame |
s+[N] / s-[N] | Ajuster la vitesse par défaut de ±N mm/trame |
stop | Remettre toutes les vitesses à zéro |
reset | Remettre la vitesse à zéro et revenir à l'origine |
h | Afficher l'aide |
Appuyez sur Ctrl+C (ou Ctrl+D / EOF) pour quitter.
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.mountLes 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 :
| Thread | Rôle |
|---|---|
| Thread principal | Lit std::getline(std::cin, ...), analyse les jetons, met à jour nav_vel[] et default_step |
| Thread de rappel WebSocket | Fait 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
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