Aller au contenu principal

05. Contrôle de position

par set_cursor_position Déplacez le curseur de « Inverse3 » vers la position souhaitée.Les modèles d'interaction varient d'une langue à l'autre.——En C++, on utilise des cibles aléatoires ponctuelles, tandis qu'en Python, on utilise des mouvements continus pilotés par le clavier.

Contenu pédagogique :

  • Utilisation set_cursor_position Mise en œuvre du contrôle en mode position
  • Deux modèles d'interaction différents correspondant à une même commande de base
  • Limiter la cible à la sphère de l'espace de travail — le rayon utilisé parMinverse est plus petit que celui de Inverse3
  • Configurer les paramètres par défautde l'espace de travail afin que le point d'origine soit situé au centre de l'espace de travail

Processus de travail​

C++ (modèle à cibles aléatoires)​

  1. Lancer un thread d'entrée en arrière-plan pour lire les frappes tamponnées ligne par ligne à partir de l'entrée standard (stdin) (n,+,-,q).
  2. Activer WebSocket. S'enregistrer dès la réception de la première trame de données d'état. Fichier de configuration de session, puis configurer configure.preset: arm_front_centered。Générer la première cible aléatoire à l'intérieur de la sphère (échantillonnage par rejet, rayon de 0,08 m).
  3. À chaque cycle, envoyer un message à la cible actuelle set_cursor_position Commande. Le curseur suit la cible en douceur : le serveur limite la vitesse et effectue une interpolation.
  4. Lorsque l'utilisateur saisit n Lorsque vous appuyez sur la touche ENTRÉE, le thread de saisie génère une nouvelle cible aléatoire.+ / - Régler la vitesse ;q Quitter.

Python (déplacer le modèle en maintenant le bouton enfoncé)​

  1. Activer WebSocket. À la réception de la première trame de données d'état, vérifier status.calibrated——Si l'appareil n'a pas encore été étalonné, un message s'affiche pour en informer l'utilisateur.
  2. Lire config.type, pour sélectionner le rayon de l'espace de travail (minverse est de 0,04 m, et de 0,10 m dans les autres cas).
  3. Inscription Fichier de configuration de session, puis configurer configure.preset: arm_front_centered。
  4. À chaque cycle : interroger l'état du clavier (W/A/S/D/Q/E), en appuyant dans la direction de chaque axe sur lequel on appuie SPEED Mettre à jour la position cible, la limiter à l'intérieur de la sphère de l'espace de travail, puis envoyer set_cursor_position。Appuyez sur R Il est possible de réinitialiser la cible à l'origine.

Paramètres​

NomValeur par défaut (C++)Valeur par défaut (Python)Utilisation
workspace_radius / RADIUS_INVERSE30.08 m0.10 m (Inverse3) / 0.04 m (Minverse)Rayon de la sphère cible
speed_step / SPEED0.01 / à chaque pression sur une touche0.00005 m / par cyclePas de pas par interaction
PRINT_EVERY_MS—100Régulation à distance du débit (Python)
Fichier de configuration de sessionco.haply.inverse.tutorials:position-controlIdentiqueÀ utiliser pour l'identification dans Haply Hub
Contrôle d'étalonnage (Python)

Les instances Python commencent à vérifier les données d'état à partir de la première image. status.calibrated, si l'appareil n'est pas calibré, un message d'avertissement s'affiche. La version C++ part du principe que le calibrage a déjà été effectué.

Champs d'état lus​

  • data.inverse3[0].device_id ——Utilisé pour la construction de commandes
  • data.inverse3[0].state.cursor_position ——Données de télémesure
  • (Python, première image uniquement)data.inverse3[0].config.type —— Permet de choisir entre les rayons de Inverse3 et Minverse
  • (Python, première image uniquement)data.inverse3[0].status.calibrated ——Si la valeur est « false », afficher un message d'avertissement à l'utilisateur

Envoyer / Recevoir​

Processus de communication​

  • C++ Lancer un thread stdin en arrière-plan, dans lequel écrire std::atomic<float> Valeurs cibles de type ; les threads WebSocket lisent ces valeurs à chaque cycle. Entrée n Lorsque vous appuyez sur ENTER, le thread de saisie génère une nouvelle cible aléatoire ; la saisie q Dans ce cas, les deux threads s'arrêtent.
  • Python Il s'agit d'une implémentation asynchrone monothread : la boucle WebSocket interroge l'état du clavier à chaque itération et met directement à jour position。

Le contenu de la charge de l'API inverse est identique : le premier cycle transporte le profil de session et configure.preset, les cycles suivants ne comportent que set_cursor_position。

Boucle asynchrone unique. Interrogation du clavier (handle_keys) s'exécute en mode inline à chaque cycle, sans utiliser de threads.config.type et status.calibrated Elle n'est lue qu'une seule fois dans les données d'état de la première image.

async with websockets.connect(URI) as websocket:
while True:
msg = await websocket.recv()
data = json.loads(msg)

if first_message:
first_message = False
device_id = data["inverse3"][0]["device_id"]
radius = get_workspace_radius(data["inverse3"][0].get("config", {}))
# Handshake: profile + preset (one-shot)
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": device_id,
"configure": {"preset": {"preset": "arm_front_centered"}},
}],
}
else:
# Per tick: update position from keyboard (classic polling, not shown), send command
position = handle_keys(position, radius)
request_msg = {
"inverse3": [{
"device_id": device_id,
"commands": {"set_cursor_position": {"position": position}},
}],
}

await websocket.send(json.dumps(request_msg))
Fourni avec le programme d'installation du SDK

Le tutoriel n° 05 est également installé localement avec le SDK — vous le trouverez dans le répertoire d'installation du service, sous tutorials/05-haply-inverse-position-control/ Rechercher dans.

Code source : Python · C++ · C++ Glaze

Contenu associé : Commandes de contrôle (set_cursor_position) · Montage et espace de travail (paramètres par défaut) · Type (vec3) · Tutoriel n° 6 (Combinaisons)