Passer directement au contenu principal

05. Contrôle de position

set_cursor_position À l'aide deInverse3 , déplacez le curseur vers la position souhaitée.Les modèles d'interaction varient selon la langue. — Le C++ utilise des cibles aléatoires ponctuelles, tandis que Python utilise des mouvements générés par une séquence de touches au clavier.

Contenu pédagogique :

  • Pour la commande en mode de position set_cursor_position Mode d'emploi
  • Deux modèles d'interaction différents pour une même commande de base
  • Serrage sur la sphère de l'espace de travail à la position cible — Minverse utilise un rayon inférieur à celui indiqué sur Inverse3
  • Configurerles paramètres prédéfinis de l'espace de travail de manière à ce que le point d'origine se trouve au centre de celui-ci

Flux de travail​

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

  1. Les entrées clavier mises en mémoire tampon par ligne provenant de l'entrée standard (n,+,-,q) et lance un thread d'entrée en arrière-plan.
  2. Ouvrez WebSocket. Dans la première trame d'état,Profil de session en l'enregistrant,configure.preset: arm_front_centered Configurer. Générer une première cible aléatoire à l'intérieur de la sphère (échantillonnage par rejet, rayon de 0,08 m).
  3. À chaque tick, par rapport à l'objectif actuel, set_cursor_position La commande est envoyée. Le curseur la suit en douceur — la limitation du débit et l'interpolation sont gérées côté serveur.
  4. L'utilisateur n Lorsque vous appuyez sur ENTER, le thread de saisie génère une nouvelle cible aléatoire.+ / - pour régler la vitesse, etq et se termine par.

Python (modèle de déplacement par appui long)​

  1. Ouvrez WebSocket. Dans la première trame d'état, status.calibrated Vérifie si l'appareil a déjà été calibré et, si ce n'est pas le cas, en informe l'utilisateur.
  2. config.type Il lit ces données et détermine le rayon de l'espace de travail (minverse (0,04 m dans ce cas, et 0,10 m dans les autres cas).
  3. Profil de session en l'enregistrant,configure.preset: arm_front_centered Configurez-le.
  4. À chaque clic, l'état du clavier (W/A/S/D/Q/E) et de déterminer la position cible le long de chaque axe sur lequel une pression est exercée SPEED Mettre à jour uniquement la partie nécessaire, la fixer à l'intérieur de la sphère de l'espace de travail, etset_cursor_position Je vais l'envoyer.R Nous réinitialisons ainsi nos objectifs en revenant à la case départ.

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 balle cible
speed_step / SPEED0.01 / Appuyer sur0.00005 m / tickDistance parcourue par opération
PRINT_EVERY_MS—100Limitation de la fréquence d'émission des données de télémétrie (Python)
Profil de sessionco.haply.inverse.tutorials:position-controlidemHaply Utilisé pour l'identification sur le hub
Vérification de l'étalonnage (Python)

Les variantes de Python, à partir du cadre d'état initial, status.calibrated Vérifie si l'appareil est calibré et, si ce n'est pas le cas, en informe l'utilisateur. La variante en C++ part du principe que le calibrage est terminé.

Champ d'état de lecture​

  • data.inverse3[0].device_id — Utilisé pour la construction de commandes
  • data.inverse3[0].state.cursor_position — Télémétrie
  • (Python, première image uniquement)data.inverse3[0].config.type — Choisir entre les rayons Inverse3 et Minverse
  • (Python, première image uniquement)data.inverse3[0].status.calibrated — Si la valeur est « false », l'utilisateur en est informé

Émission et réception​

Flux de travail des communications​

  • C++ est,std::atomic<float> Exécute le thread d'entrée standard en arrière-plan chargé d'écrire les valeurs cibles. Le thread WebSocket lit ces valeurs à chaque tick.n En appuyant sur ENTER, le fil de discussion génère une nouvelle cible aléatoire, etq Ce qui met fin aux deux fils de discussion.
  • Python Il s'agit d'un traitement asynchrone monothread. La boucle WebSocket interroge l'état du clavier à chaque tick, etposition le mettra directement à jour.

La charge utile de l'API inverse est identique. Lors du premier tick, le profil de session et configure.preset envoyer, puis lors des ticks suivants, set_cursor_position Nous n'enverrons que cela.

Il s'agit d'une boucle asynchrone unique. Interrogation du clavier (handle_keys) s'exécute en ligne à chaque tick et n'utilise pas de thread.config.type et status.calibrated est lu une seule fois à partir de la première trame d'état.

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))
Inclus dans le programme d'installation du SDK

Le tutoriel 05 est également installé localement avec le SDK. Dans le répertoire d'installation du service, sous tutorials/05-haply-inverse-position-control/ Veuillez consulter [...].

Source : Python · C++ · C++ Glaze

À lire également : Commandes de contrôle (set_cursor_position) · Support et espace de travail (préréglages) · Type (vec3) · Tutoriel 06 (Combiné)