Aller au contenu principal

09. Navigateur d'espaces de travail WebSocket

en diffusant en continu sur un canal WebSocket set_transform Commandes, appareils de navigation en temps réelEmplacement de l'espace de travail. Ce tutoriel utilise le protocole HTTP pour détecter les sessions et les appareils (à l'instar de Tutoriel n° 08 (identiques), puis ouvrir un WebSocket et envoyer les mises à jour de position à chaque tick.

Le tableau ci-dessous illustre la différence entre ces deux opérations de transformation :

OpérationTutorielExemples d'utilisation
configure.mount — Persistance des transformations de montage08À définir une seule fois (ou à modifier très rarement) pour décrire la configuration physique de l'installation de l'équipement
set_transform — Persistance des transformations de l'espace de travail09(Ce tutoriel)Bien qu'il s'agisse également d'une persistance, les données peuvent être transmises en continu à chaque tick, ce qui permet une navigation en temps réel dans l'espace de travail.

Ces deux commandes peuvent être exécutées via HTTP et WebSocket utilisées, et toutes sontpersistant——Le service mémorise la dernière valeur que vous avez envoyée. La différence entre les deux réside dans leur utilisation et leur fréquence de mise à jour :configure.mount Une optimisation a été effectuée pour les mises à jour à faible fréquence (paramètres physiques), tandis que set_transform Optimisation pour la transmission en flux continu à haute fréquence (navigation dans les scénarios).

Lorsque l'origine de l'espace de travail doit suivre un objet dont la position varie au cours de l'exécution, veuillez utiliser set_transform——Par exemple, suivre les mouvements de la main, animer des décalages programmés ou permettre à l'opérateur d'ajuster en temps réel l'espace de travail virtuel.

Il existe une relation parent-enfant entre les montages et les espaces de travail

Pris isolément,configure.mount et set_transform Cela semble produire le même effet, mais il existe une différence entre les deuxLes relations père-fils: Dans le système de coordonnées, la transformation de l'espace de travail est appliquée à la montureci-dessus(device → basis → mount → workspace → application). Pour consulter la liste complète, voir Montage et espace de travail。

Cas d'utilisation​

  • Navigation en temps réel dans l'espace de travail. Déplacement du curseur de l'espace de travail de l'appareil (c'est-à-dire la zone d'enveloppe accessible par l'effecteur terminal) sans interrompre la simulation tactile.
  • Alignement piloté par l'opérateur. Demandez à la personne se trouvant sur l'autre terminal de maintenir une touche de direction enfoncée pour faire coulisser l'espace de travail pendant l'exécution de l'application tactile principale — cette méthode est idéale pour effectuer un calibrage du bureau pour chaque utilisateur lors d'une session en temps réel.
  • Mouvement programmatique de l'espace de travail. La position de l'espace de travail est contrôlée par des scripts (pilotés par le son, par des forces physiques, etc.) ; à chaque tick, seul un patch de transformation contenant la position est envoyé.

Conditions préalables​

Le tutoriel n° 9 nécessite unesession WebSocket active, c'est-à-dire un client Inverse3 déjà présent dans la boucle tactile en cours d'exécution. Le tutoriel n° 9 se connectera ensuite à cette session et effectuera un panoramique en temps réel de son espace de travail.

La méthode la plus rapide pour démarrer une session

Ouvrez le Hub «Haply » et lancezla démo Orb. Une session tactile persistante s’ouvrira, que vous pourrez immédiatement utiliser comme cible :

./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. En suivant le tutoriel n° 09 « Déplacer l'espace de travail », vous pourrez déplacer l'ensemble de la scène en temps réel et obtenir ainsi un retour visuel immédiat.

Tout autre tutoriel utilisant la boucle tactile (01 à 07) fonctionne de la même manière. Lancez-le d'abord dans un terminal, puis lancez le tutoriel 09 dans un deuxième terminal pour qu'il détecte 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

Contrôle​

Maintenez une touche enfoncée pour continuer à vous déplacer ; relâchez-la pour vous arrêter.

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

Principe de fonctionnement​

Étape 1 — Session HTTP et détection des appareils​

Ce tutoriel réutilise et Tutoriel n° 08 idem discover_session() / discover_device() Fonctions auxiliaires : exécuter en premier GET /sessions(Si l'on spécifie --session, alors c'est GET /sessions/<selector>), puis exécutez GET /devices(ou utilisez directement --device). Ces deux fonctions auxiliaires acceptent les mêmes paramètres de ligne de commande, et SESSION_HELP Le texte est identique : les sélecteurs issus des tutoriels 00 ou 08 peuvent être utilisés ici sans aucune modification.

Étape 2 — Poignée de main entre la session WebSocket et le premier message​

Ce tutoriel ouvrira un lien vers ws://localhost:10001 WebSocket.Uniquement à la réception du premier message, il envoie les informations d'enregistrement de la configuration 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 sont omis session Champ — Envoi uniquement inverse3 Tableau de commandes.

Étape 3 — À chaque tick, set_transform​

set_transform AccepterTransformation partielle——Il suffit d'inclure les champs que vous souhaitez modifier. Dans ce tutoriel, seules les coordonnées de position sont envoyées ; la rotation et le zoom conservent les valeurs par défaut de la session (c'est-à-dire configure.mount (les valeurs définies, 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 à chaque tick. À une fréquence d'environ 1 kHz, le service réapplique le calcul à chaque tick. set_transform(conservation d'ordre zéro), ce qui signifie que l'espace de travail restera à l'endroit où vous vous êtes arrêté lors de votre dernier enregistrement.

set_transform et configure.mount La différence

Ces deux commandes enregistrent une transformation persistante pour chaque session, mais dans le pipeline, la transformation de l'espace de travail se trouve dans le montageci-dessus(Voir Montage et espace de travail). Lorsque le tutoriel 09 envoie des données en continu à chaque tick set_transform À ce moment-là, chaque nouvelle trame WebSocket remplace la transformation de l'espace de travail précédemment transmise en continu ; par conséquent, toute autre transmission en continu vers le même appareil set_transform Les données des clients seront toutes écrasées lors du prochain tick.configure.mount Elles sont indépendantes les unes des autres et conservent leurs valeurs inchangées. En pratique, on choisit un canal pour chaque catégorie de fonctions : le montage sert à la configuration physique,set_transform Pour la navigation en temps réel.

Modèle de threads (C++)​

Ce tutoriel C++ utilise deux threads pour partager un compteur de position :

ThreadFonctions
Fil principalLire std::getline(std::cin, ...), analyse du jeton, mise à jour nav_vel[] et default_step
Fil de discussion des rappels WebSocketUtilisation nav_vel[] * dt faire avancer nav_pos[], sérialisation set_transform et envoyer

std::mutex nav_mutex Protection nav_pos[],nav_vel[] et default_step。last_tick Horodatage et first_ws_msg La variable `WS` est une variable locale de la fonction de rappel ; aucun verrou mutuel 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 a été installé localement avec le SDK. Veuillez vous rendre dans le répertoire d'installation du service, sous tutorials/09-haply-inverse-ws-remote-control/ Rechercher dans.

Contenu associé : set_transform Ordre · Session — Échange d'informations d'identification lors du premier message · Montage et espace de travail · Sélecteur · Tutoriel 08 — Configuration à distance via HTTP · Tutoriel 07 — Basis et montage