Skip to main content
Version : 3.5.x

06. Combiné (Inverse3 Wireless VerseGrip)

Tutoriel pour deux appareils : pointez la poignée et maintenez un bouton enfoncé pour déplacer le Inverse3 dans cette direction. Le curseur est confiné à l'intérieur d'un espace de travail sphérique.

Ce que vous apprendrez :

  • Lecture de deux types d'appareils dans le même cadre d'état (inverse3 et wireless_verse_grip)
  • Déterminer la direction vers laquelle pointe la poignée à partir de sa quaternion (local +Y axe)
  • Utilisation de set_cursor_position pour diriger le curseur vers une cible calculée
  • Fixation de la cible dans un espace de travail sécurisé — Minverse un rayon plus petit qu'Inverse3
  • Définir un réglage prédéfini de l'espace de travail (arm_front_centered) de sorte que le point d'origine se trouve au milieu de la portée

Flux de travail

  1. Découvrez ces deux appareils :
    • C++ requête sur les variantes GET /devices via HTTP au démarrage, puis afficher une invite de calibrage et attendre que l'on appuie sur ENTRÉE.
    • Python lit les deux identifiants de périphérique à partir de la première trame d'état WebSocket.
  2. Enregistrer le profil de session et définir configure.preset: arm_front_centered dès le premier message (poignée de main en une seule étape).
  3. À chaque coup de manivelle : lisez les indications de la poignée orientation et buttons.{a, b} État.
  4. Si un bouton de mouvement est maintenu enfoncé, calculez la direction de la poignée dans l'espace mondial (R(q) · ĵ — l'unité pivotée autour de l'axe +Y) et l'accumuler jusqu'à la position cible mise à l'échelle par SPEED.
  5. Placez la cible à l'intérieur de la sphère de travail et envoyez-la via set_cursor_position.
  6. (Python uniquement) Adaptez le rayon de la sphère en fonction de l'appareil config.typeminverse = 0,04 m, tout le reste = 0,10 m.

Paramètres

NomPar défautObjectif
SPEED0.01 m/tickDéplacement par pas pendant qu'un bouton est maintenu enfoncé
RADIUS_INVERSE30.10 mRayon de serrage de l'espace de travail pour Inverse3 Inverse3x
RADIUS_MINVERSE0.04 mRayon de la pince de l'espace de travail pour Minverse Python uniquement — le C++ utilise des valeurs fixes) 0.10)
PRINT_EVERY_MS200Manette de télémétrie
Nom du profil de sessionco.haply.inverse.tutorials:combinedIdentifie cette simulation dans Haply
Effectuez un étalonnage avant de démarrer
  • Laissez Inverse3 (ou placez la poignée sur l'encrier et attendez que la LED reste allumée en continu).
  • Retirez le manche de l'encrier.
  • Maintenez la touche A ou B enfoncée et faites pivoter la poignée : le curseur se déplace dans la direction indiquée par la poignée.

Champs d'état lus

À partir du cadre d'état par tick :

  • data.inverse3[0].state.cursor_positionvec3
  • data.wireless_verse_grip[0].state.orientationquaternion
  • data.wireless_verse_grip[0].state.buttons.{a, b, c} — booléens
  • (Python, première image uniquement) data.inverse3[0].config.type — sélectionne Minverse « Inverse3 Minverse
  • (Python, première image uniquement) data.inverse3[0].status.calibrated — demande à l'utilisateur si la valeur est fausse

Envoyer / recevoir

Le calcul de conversion entre quaternions et directions (rotation +Y par R(q)) et la pince sphérique relèvent de l'algèbre linéaire classique — voir les fichiers source. Du côté de l'API inverse, il s'agit de la négociation de connexion + par tick set_cursor_position.

Boucle asynchrone unique. Python lit les deux identifiants de périphérique à partir de la première trame d'état ; la négociation établit le profil + configure.preset: arm_front_centered au premier set_cursor_position.

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))

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

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