09. WebSocket Workspace-Navigator
Naviguez dans la Espace de travail – Position d'un appareil en temps réel, en set_transform- Diffuser des commandes via le canal WebSocket. Ce tutoriel utilise le protocole HTTP pour identifier la session et l'appareil (tout comme Tutoriel 08), puis ouvre une connexion WebSocket afin d'envoyer des mises à jour de position à chaque tick.
Ce schéma illustre la différence entre deux opérations de transformation :
| Fonctionnement | Tutoriel | Utilisation typique |
|---|---|---|
configure.mount — transformation de Mount persistante | 08 | À utiliser une seule fois (ou rarement) pour décrire le montage physique de l'appareil |
set_transform — Transformation persistante de l'espace de travail | 09 (de ce mois) | Également persistant, mais peut être diffusé en continu à chaque tick pour la navigation en temps réel dans l'espace de travail |
Ces deux commandes sont disponibles via HTTP et WebSocket, et toutes deux sont persistant — Le service mémorise la dernière valeur envoyée. La différence réside dans la finalité et la fréquence de mise à jour : configure.mount est optimisé pour les mises à jour peu fréquentes (configuration physique), tandis que set_transform optimisé pour le streaming à haut débit (navigation entre les scènes).
Utilisez set_transform, lorsque l'origine de l'espace de travail doit suivre un élément dont la taille varie pendant l'exécution, par exemple une main, un décalage procédural animé ou un opérateur qui déplace l'espace de travail virtuel en temps réel.
Pris isolément, ils semblent configure.mount et set_transform pour produire le même effet, mais elles sont liés hiérarchiquement: La transformation de l'espace de travail est effectuée dans le pipeline de coordonnées auf den Mount a été utilisé (device → basis → mount → workspace → application). Vous trouverez le pipeline complet à l'adresse suivante : Support et espace de travail.
Cas d'utilisation
- Navigation en temps réel dans l'espace de travail. Déplacez l'espace de travail du curseur de l'appareil (la zone que l'effecteur terminal peut atteindre) sans interrompre la scène haptique.
- Alignement contrôlé par l'utilisateur. Demandez à une personne utilisant un deuxième terminal de maintenir les touches fléchées enfoncées pour déplacer l'espace de travail pendant que l'application haptique principale est en cours d'exécution — cette fonction est utile pour effectuer un étalonnage sur le poste de travail concerné pendant une session en cours.
- Déplacement procédural de l'espace de travail. Contrôlez la position de l'espace de travail à partir d'un script (commande audio, physique, etc.) en envoyant à chaque tick des patches de transformation de position purs.
Conditions préalables
Le tutoriel 09 nécessite une session WebSocket active, c'est-à-dire un client dont l'adresse Inverse3 est déjà active dans une boucle haptique en cours d'exécution. Le tutoriel 09 se connecte alors à cette session et déplace son espace de travail en temps réel.
Ouvrez Haply Hub et lancez la démo Orb. Une session haptique persistante s'ouvre, à laquelle vous pouvez interagir 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 au point d'origine de l'espace de travail. Lorsque vous déplacez l'espace de travail avec le tutoriel 09, toute la scène se déplace en temps réel, ce qui vous permet d'obtenir un retour visuel immédiat.
N'importe quel autre tutoriel (01 à 07) exécutant une boucle haptique fonctionne également. Lancez-le dans un terminal, puis lancez le tutoriel 09 dans un deuxième terminal afin qu'il détecte 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
Commande
- Python
- C++
Maintenez une touche enfoncée pour continuer à avancer. Relâchez-la pour vous arrêter.
| Goût | Action |
|---|---|
→ / ← | +X / −X |
↑ / ↓ | +Y / −Y |
Page Up / Page Down | +Z / −Z |
= / - | Augmenter / réduire la vitesse de navigation |
0 | Réinitialiser l'espace de travail à son état d'origine |
H | Afficher l'aide |
Esc | Quitter (Ctrl+C (ça fonctionne aussi) |
Mode ligne par ligne — Saisissez la commande, puis appuyez sur ENTRÉE.
| Commande | Action |
|---|---|
x+[N] / x-[N] | Régler la vitesse X sur ±N mm/image (utilisé sans valeur numérique) x+ (la vitesse standard actuelle) |
y+[N] / y-[N] | Régler la vitesse Y sur ±N mm/image |
z+[N] / z-[N] | Régler la vitesse Z sur ±N mm/image |
s+[N] / s-[N] | Ajuster la vitesse standard de ±N mm/image |
stop | Régler toutes les vitesses sur 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 le programme.
Fonctionnement
Étape 1 — Reconnaissance de la session HTTP et de l'appareil
Ce tutoriel utilise les mêmes fonctions auxiliaires discover_session() / discover_device() comme Tutoriel 08: GET /sessions (ou GET /sessions/<selector> mit --session), puis GET /devices (ou directement --device (utiliser). Ces deux fonctions auxiliaires acceptent les mêmes options CLI, avec une syntaxe identique SESSION_HELP-Texte — un sélecteur issu du tutoriel 00 ou 08 fonctionne ici tel quel.
Étape 2 — Session WebSocket, établissement de la connexion lors du premier message
Ce tutoriel établit une connexion WebSocket vers ws://localhost:10001. Uniquement dans le cas de la premier message reçu 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 permettent session weg — seul le tableau de commandes est envoyé inverse3.
Étape 3 — set_transform pro Tick
set_transform accepte une Transformation partielle, et uniquement les champs que vous souhaitez modifier. Ce tutoriel envoie uniquement la position ; la rotation et la mise à l'échelle restent aux valeurs par défaut de la session (les valeurs qui, le cas échéant, sont définies par configure.mount ont été fixées).
{
"inverse3": [{"device_id": "...", "commands": {"set_transform": {"transform": {"position": {"x": 0.02, "y": 0.0, "z": 0.01}}}}}]
}
La position s'incrémentant tick par tick. À une fréquence d'environ 1 kHz, le service set_transform à chaque tick (mémorisation d'ordre zéro), de sorte que l'espace de travail reste à l'endroit où vous l'avez déplacé en dernier.
set_transform contre configure.mountCes deux commandes enregistrent une transformation persistante par session. La transformation de l'espace de travail se trouve toutefois dans le pipeline auf dem Mount (voir Support et espace de travail). Tutoriel Solange 09 à chaque tick set_transform En mode streaming, chaque nouvelle trame WebSocket remplace la transformation de l'espace de travail précédemment diffusée. Un autre client qui set_transform et qui est diffusé en continu sur ce même appareil sera donc écrasé au prochain tick. configure.mount Cela n'a aucun rapport et conserve toute sa valeur. Dans la pratique, vous devriez choisir un canal par sujet : « Mount » pour la configuration physique, set_transform pour la navigation en direct.
Modèle de threading (C++)
Le tutoriel C++ utilise deux threads qui partagent un accumulateur de position :
| Fil de discussion | Rolle |
|---|---|
| Fil de discussion principal | Liest std::getline(std::cin, ...), analyse des jetons, mise à jour nav_vel[] et default_step |
| Fil de rappel WebSocket | Écrivez nav_pos[] euh nav_vel[] * dt fort, en feuilleton set_transform et envoie |
std::mutex nav_mutex protège nav_pos[], nav_vel[] et default_step. L'horodatage last_tick et le drapeau first_ws_msg sont locales dans le callback WS et ne nécessitent pas 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
};
Quelle
Le tutoriel 09 est installé localement à l'aide du SDK — vous le trouverez sous tutorials/09-haply-inverse-ws-remote-control/ dans le répertoire d'installation du service.
Sujets connexes : Commande set_transform · Sessions — Poignée de main avec le premier message · Support et espace de travail · Sélecteurs · Tutoriel 08 — Configuration à distance via HTTP · Tutoriel 07 — Base et support