Passer directement au contenu principal

09. Navigateur d'espaces de travail WebSocket

via un canal WebSocket set_transform En diffusant les commandes, l'appareilNaviguer en temps réel dans l'espace de travailC'est possible. Dans ce tutoriel, nous allons détecter les sessions et les appareils à l'aide du protocole HTTP (Tutoriel n° 08 (C'est exactement la même méthode). Ensuite, on ouvre un WebSocket et on envoie une mise à jour de position à chaque tick.

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

OpérationTutorielApplications typiques
configure.mount — Conversion de montage permanente08À définir une seule fois (ou rarement) pour décrire l'installation physique de l'appareil
set_transform — Transformation durable de l'espace de travail09(Ce tutoriel)Ceci est également permanent, mais permet une navigation en temps réel dans l'espace de travail grâce à la diffusion en continu à chaque tick.

Ces deux commandes HTTP et WebSocket accessibles via, et les deuxPermanent. Le service mémorise la dernière valeur envoyée. La différence réside dans l'objectif et la fréquence de mise à jour.configure.mount est optimisé pour les mises à jour peu fréquentes (configuration physique), tandis que,set_transform Il est optimisé pour le streaming à haute fréquence (navigation entre les scènes).

Si vous devez suivre des éléments dont le point d'origine de l'espace de travail varie au cours de l'exécution (suivi des mouvements de la main, animation d'un décalage procédural, ajustement en temps réel de l'espace de travail virtuel par l'opérateur, etc.),set_transform Veuillez utiliser ceci.

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

Si l'on examine chaque cas séparément,configure.mount et set_transform Cela semble produire le même effet, mais les deuxIl s'agit d'une relation parent-enfant. Pipeline de coordonnées (device → basis → mount → workspace → application) Dans ce cas, la conversion de l'espace de travail correspond au montage deen hautS'applique. En ce qui concerne l'ensemble du pipeline,Support et espace de travailVeuillez consulter [...].

Cas d'utilisation​

  • Navigation dans l'espace de travail en temps réel. Permet de déplacer le curseur de l'espace de travail de l'appareil (zone limite accessible par l'effecteur terminal) sans interrompre la scène tactile.
  • Alignement par l'opérateur. Pendant l'exécution de l'application tactile principale, cela permet à une personne se trouvant sur un deuxième terminal de déplacer l'espace de travail en maintenant les touches fléchées enfoncées. Cette fonctionnalité est utile pour effectuer un calibrage du bureau pour chaque utilisateur pendant une session en direct.
  • Fonctionnement procédural de l'espace de travail. La position de l'espace de travail est contrôlée à partir de scripts (à réaction sonore, à commande physique, etc.) en envoyant, à chaque tick, un patch de transformation ne contenant que la position.

Conditions préalables​

Le tutoriel 09 nécessiteune session WebSocket active. Il s'agit donc d'un client qui dispose déjà d'un objet ` Inverse3 ` dans une boucle tactile en cours d'exécution. Le tutoriel 09 se connecte à cette session et déplace l'espace de travail en temps réel.

Comment démarrer une session le plus rapidement possible ?

Haply Ouvrez Hub et lancez la démoOrb. Une session tactile permanente, que vous pouvez immédiatement utiliser, s'ouvre :

./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. Dans le tutoriel n° 9, lorsque vous déplacez l'espace de travail, la scène entière se déplace en temps réel, ce qui vous permet d'obtenir un retour visuel immédiat.

Les autres tutoriels (01 à 07) qui exécutent la boucle tactile fonctionnent de la même manière. Lancez-les dans un terminal, puis lancez le tutoriel 09 dans un autre terminal pour permettre la détection interactive des sessions.

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, le personnage se déplace en continu. Relâchez-la pour l'arrêter.

CléOpération
→ / ←+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 (mais vous pouvez aussi y mettre fin)

Fonctionnement​

Étape 1 — Détection des sessions HTTP et des appareils​

Ce tutoriel est destiné à,Tutoriel n° 08 idem discover_session() / discover_device() Nous réutilisons le helper. Tout d'abord, GET /sessions(--session Si vous souhaitez spécifier GET /sessions/<selector>), puis GET /devices(ou --device (à utiliser directement) est appelée. Ces deux fonctions d'aide utilisent le même indicateur CLI et le même SESSION_HELP Pour accepter du texte, vous pouvez utiliser ici aussi les sélecteurs des tutoriels 00 ou 08, sans les modifier.

Étape 2 — Établissement de la session WebSocket et échange de messages d'initialisation​

Dans ce tutoriel,ws://localhost:10001 Ouvre une connexion WebSocket vers.Uniquement le premier message reçuÀ cette occasion, nous envoyons 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}}}}}]
}

Dans les ticks suivants, session en omettant,inverse3 Seules les séquences de commandes sont envoyées.

Étape 3 — Par tick set_transform​

set_transform はConversion partiellesont acceptées. En d'autres termes, vous pouvez spécifier uniquement les champs que vous souhaitez modifier. Dans ce tutoriel, seule la position sera envoyée ; la rotation et le redimensionnement conserveront les valeurs par défaut de la session (configure.mount (si une valeur a été définie, alors cette valeur).

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

La position est cumulée à chaque tick. À une fréquence d'environ 1 kHz, le service effectue cette opération à chaque tick. set_transform est réappliquée (maintien d'ordre zéro). Par conséquent, l'espace de travail reste à la dernière position envoyée.

set_transform et configure.mount Comparaison

Ces deux commandes conservent une conversion permanente pour chaque session. Toutefois, la conversion de l'espace de travail est appliquée dans le pipeline lors du montage de laen hautSe trouve à (Support et espace de travail(voir). Le tutoriel n° 09 explique, à chaque étape, set_transform Pendant la diffusion en continu, chaque fois qu'une nouvelle trame WebSocket est reçue, la transformation de l'espace de travail diffusée précédemment est remplacée. Par conséquent, sur le même appareil, set_transform Les autres clients qui diffusent ce flux seront remplacés lors du prochain tick.configure.mount Ils sont indépendants et conservent leurs valeurs. En pratique, veuillez choisir un canal par sujet : « Montage » pour la configuration physique et « Navigation en direct » pour set_transform On utilise.

Modèle de threads (C++)​

Dans ce tutoriel C++, nous utilisons deux threads qui partagent un compteur de position :

Fil de discussionRôle
Fil principalstd::getline(std::cin, ...) lire, analyser le jeton, puisnav_vel[] et default_step Mettre à jour
Fil de rappel WebSocketnav_vel[] * dt en utilisant nav_pos[] et poursuivre,set_transform le sérialiser et l'envoyer

std::mutex nav_mutex は nav_pos[],nav_vel[],default_step les protège.last_tick l'horodatage et first_ws_msg Les indicateurs sont des valeurs locales à la fonction de rappel 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
};

Source​

Inclus dans le programme d'installation du SDK

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

À lire également : set_transform Commande · Session — Échange d'informations d'identification lors du premier message · Support et espace de travail · Sélecteur · Tutoriel 08 — Configuration à distance HTTP · Tutoriel n° 7 — Base et support