Passer directement au contenu principal

06. Intégration (Inverse3 + VerseGrip sans fil)

Ce tutoriel concerne deux appareils. En orientant la poignée dans une direction et en maintenant le bouton enfoncé, le curseur de Inverse3 se déplace dans cette direction. Le curseur reste confiné à l'intérieur de l'espace de travail sphérique.

Contenu pédagogique :

  • Deux types d'appareils au sein d'un même état (inverse3 et wireless_verse_grip) lire
  • quaternion À partir de l'orientation de la poignée (locale) +Y Retirer l'axe
  • set_cursor_position déplacer le curseur vers la cible calculée à l'aide de
  • Limiter la cible à l'intérieur d'une sphère de travail sécurisée. La fonction «Minverse » utilise un rayon inférieur à celui de « Inverse3 ».
  • Préréglages de l'espace de travail(arm_front_centered) et faire en sorte que le point d'origine se trouve au centre de la zone d'atteinte

Flux de travail​

  1. Détecte les deux appareils :
    • C++ La version est chargée via HTTP au démarrage GET /devices Consultez la valeur, affichez l'invite de calibrage et attendez que l'utilisateur appuie sur la touche ENTER.
    • Python lit les identifiants des deux appareils à partir de la première trame d'état WebSocket.
  2. Dans le premier message, Profil de session en l'enregistrant,configure.preset: arm_front_centered Configurer (poignée de main en une seule étape).
  3. À chaque clic, la poignée orientation et buttons.{a, b} Il lit l'état.
  4. Si le bouton de déplacement est enfoncé, l'orientation dans l'espace mondial de la poignée (R(q) · ĵ, calculer l'unité après rotation (axe +Y), etSPEED On ajoute la valeur mise à l'échelle à la position cible.
  5. Limiter la cible à l'intérieur de la sphère de l'espace de travail, etset_cursor_position Je l'enverrai par...
  6. (Python uniquement) Les périphériques config.type On ajuste le rayon de la sphère en fonction de cela.minverse Dans ce cas, elle est de 0,04 m ; dans les autres cas, elle est de 0,10 m.

Paramètres​

NomPar défautUtilisation
SPEED0.01 m/tickÉtapes de déplacement pendant que le bouton est enfoncé
RADIUS_INVERSE30.10 mInverse3 / Rayon limite de l'espace de travail pour Inverse3x
RADIUS_MINVERSE0.04 mMinverse Rayon limite de l'espace de travail (Python uniquement — pour C++, c'est 0.10 (fixe)
PRINT_EVERY_MS200Limite de fréquence d'envoi des données de télémétrie
Nom du profil de sessionco.haply.inverse.tutorials:combinedHaply Identifier cette simulation dans Hub
Effectuer l'étalonnage avant l'exécution
  • Inverse3 Effectuez l'auto-étalonnage (ou placez le stylo dans le réservoir d'encre et attendez que la LED s'allume).
  • Retirez la poignée de l'encrier.
  • Faites pivoter la molette tout en maintenant la touche A ou B enfoncée. Le curseur se déplace dans la direction vers laquelle est orientée la molette.

Lire le champ « state »​

On lit les éléments suivants dans le cadre « state » de chaque tick :

  • 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} — Valeur booléenne
  • (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 », afficher une invite à l'utilisateur

Envoyer / Recevoir​

Calcul permettant de déterminer une direction à partir d'un quaternion (R(q) et +Y (rotation) et le serrage par sphère constituent des calculs classiques de l'algèbre linéaire. Pour plus de détails, veuillez consulter le fichier source. Du côté de l'API inverse, la négociation de connexion et, à chaque tick, set_cursor_position effectue l'appel.

Il s'agit d'une boucle asynchrone unique. Python lit les identifiants des deux périphériques à partir de la première trame d'état. Lors de la négociation de connexion, la première set_cursor_position avec le profil et configure.preset: arm_front_centered est attribué.

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

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

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

À lire également : Commandes de contrôle (set_cursor_position) · type (quaternion, vec3) · Support et espace de travail (préréglages) · Tutoriel 03 (VG sans fil) · Tutoriel 05 (Contrôle de position)