Aller au contenu principal

06. Ensemble (Inverse3 + VerseGrip sans fil)

Tutoriel pour deux périphériques : orientez la poignée dans une direction donnée et maintenez le bouton enfoncé pour déplacer le curseur de Inverse3 dans cette direction. Le curseur est confiné à un espace de travail sphérique.

Vous apprendrez :

  • Lire deux types d'appareils dans la même trame d'état (inverse3 et wireless_verse_grip)
  • À partir de la poignée quaternions(local) +Y Extraction de la direction d'orientation dans l'axe)
  • Utilisation set_cursor_position Déplacer le curseur vers la position calculée
  • Limiter la cible à un espace de travail sphérique sécurisé — le rayon utilisé parMinverse est inférieur à Inverse3
  • Paramètres Préréglages d'espace de travail(arm_front_centered), de manière à ce que l'origine se trouve au centre de la zone accessible

Processus de travail​

  1. Deux appareils ont été détectés :
    • Au démarrage,C++ les différentes variantes via une requête HTTP GET /devices, puis imprimez les instructions de calibrage et attendez que la touche ENTER soit enfoncée.
    • Python lit les identifiants des deux appareils à partir de la première trame d'état WebSocket.
  2. S'inscrire dès le premier message Fichier de configuration de session, puis configurer configure.preset: arm_front_centered(Poignée de main unique).
  3. À chaque cycle : lecture de la poignée orientation ainsi que buttons.{a, b} État.
  4. Si l'on maintient le bouton « Mouvement » enfoncé, l'orientation de la poignée dans le système de coordonnées mondial est calculée (R(q) · ĵ, c'est-à-dire l'unité après rotation autour de l'axe +Y), puis en appuyant sur SPEED Après mise à l'échelle, superposer à l'emplacement cible.
  5. Limiter la cible à l'intérieur de la sphère de l'espace de travail, et à l'aide de set_cursor_position Envoyer.
  6. (Python uniquement) En fonction de l'appareil config.type Réglage du rayon de la sphère ——minverse est de 0,04 m, tandis que pour tous les autres types, elle est de 0,10 m.

Paramètres​

NomValeur par défautUtilisation
SPEED0.01 m/cycleDistance parcourue à chaque pas lorsque le bouton est maintenu enfoncé
RADIUS_INVERSE30.10 mInverse3 / Rayon limite de l'espace de travail d'Inverse3x
RADIUS_MINVERSE0.04 mMinverse Rayon de limitation de l'espace de travail (applicable uniquement à Python — en C++, il est codé en dur à 0.10)
PRINT_EVERY_MS200Intervalle de régulation de la sortie de télémesure
Nom du profil de sessionco.haply.inverse.tutorials:combinedIdentifier cette simulation dans Haply Hub
Effectuer un étalonnage avant la mise en service
  • Laissez le Inverse3 se calibrer automatiquement (ou placez le stylo sur la cartouche d'encre et attendez que la LED reste allumée en continu).
  • Retirez le manche de la cartouche d'encre.
  • Maintenez la touche A ou B enfoncée et tournez la poignée : le curseur se déplacera dans la direction indiquée par la poignée.

Champs d'état lus​

Lecture à partir de la trame d'état de chaque cycle :

  • data.inverse3[0].state.cursor_position — vec3
  • data.wireless_verse_grip[0].state.orientation — quaternion
  • data.wireless_verse_grip[0].state.buttons.{a, b, c} — Valeurs booléennes
  • (Python, première image uniquement)data.inverse3[0].config.type —— Rayon utilisé pour choisir entre Inverse3 et Minverse
  • (Python, première image uniquement)data.inverse3[0].status.calibrated —— Si la valeur est « false », afficher un message à l'utilisateur

Envoyer / Recevoir​

Calcul de la direction à partir d'un quaternion (à l'aide de R(q) Rotation +Y) ainsi que les contraintes sphériques constituent toutes des opérations classiques d'algèbre linéaire ; pour plus de détails, voir le fichier source. La partie « API inverse » comprend la procédure de poignée de main ainsi que, pour chaque cycle, set_cursor_position Composition des appels.

Boucle asynchrone unique. Python lit les identifiants des deux appareils à partir de la première trame d'état ; la procédure de négociation établit le profil de configuration + configure.preset: arm_front_centered Ajouté à la première fois set_cursor_position Appel en cours.

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

if first_message:
first_message = False
inverse3_id = data["inverse3"][0]["device_id"]
grip_id = data["wireless_verse_grip"][0]["device_id"]
radius = get_workspace_radius(data["inverse3"][0].get("config", {}))

# Handshake: profile + preset + first position command
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": inverse3_id,
"configure": {"preset": {"preset": "arm_front_centered"}},
"commands": {"set_cursor_position": {"position": position}},
}],
}
else:
# Per tick: update position from grip pointing direction (classic math, not shown), send
request_msg = {
"inverse3": [{
"device_id": inverse3_id,
"commands": {"set_cursor_position": {"position": position}},
}],
}

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

Le tutoriel 06 sera également installé localement avec le SDK — veuillez vous rendre dans le répertoire d'installation du service, sous tutorials/06-haply-inverse-combined/ Rechercher dans.

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

Contenu associé : Commandes de contrôle (set_cursor_position) · Type (quaternion, vec3) · Installation et espace de travail (paramètres par défaut) · Tutoriel 03 (VG sans fil) · Tutoriel 05 (Contrôle de position)