Aller au contenu principal

06. Ensemble (Inverse3 + Wireless VerseGrip)

Tutoriel avec deux appareils : alignez la poignée et maintenez une touche enfoncée pour déplacer le curseur depuis Inverse3 dans cette direction. Le curseur est confiné dans un espace de travail sphérique.

Ce que vous apprendrez :

  • Lecture de deux types d'appareils à partir d'une même trame d'état (inverse3 et wireless_verse_grip)
  • Détermination du sens d'orientation de la poignée à partir de sa Quaternion (local +Y-axe)
  • Utilisation de set_cursor_position, pour déplacer le curseur vers une cible calculée
  • Limitation de la cible à une sphère de travail sécurisée – Minverse utilise un rayon plus petit que Inverse3
  • Définition d'un Préréglages de l'espace de travail (arm_front_centered), afin que le point d'origine se trouve au milieu de la portée

Déroulement​

  1. Les deux appareils détectent :
    • C++- Les variantes demandent les informations au démarrage via HTTP GET /devices ab, affichent ensuite une invite de calibrage et attendent que l'on appuie sur ENTER.
    • Python lit les deux identifiants de périphérique à partir de la première trame d'état de WebSocket.
  2. Enregistrez le Fiche de séance et indiquez-le dans votre premier message configure.preset: arm_front_centered (poignée de main unique).
  3. À chaque cycle : lisez les orientation des griffes et l'état de buttons.{a, b}.
  4. Si une touche de déplacement est maintenue enfoncée, calculez la direction de la poignée dans le système de coordonnées mondial (R(q) · ĵ – l'axe unitaire pivoté (+Y) et additionnez-le, mis à l'échelle par SPEED, jusqu'à la position cible.
  5. Limitez le point cible à l'intérieur de la sphère de l'espace de travail et envoyez-le via set_cursor_position.
  6. (Python uniquement) Ajustez le rayon de la sphère en fonction de config.type de l'appareil – minverse = 0,04 m, toutes les autres = 0,10 m.

Paramètres​

NomValeur par défautObjet
SPEED0.01 m/tickIncrément, tant qu'une touche est maintenue enfoncée
RADIUS_INVERSE30.10 mRayon de délimitation de l'espace de travail pour Inverse3 / Inverse3x
RADIUS_MINVERSE0.04 mRayon de délimitation de l'espace de travail pour Minverse (Python uniquement – le C++ est fixé à 0.10 (codé)
PRINT_EVERY_MS200Limitation de la télémétrie
Nom du profil de sessionco.haply.inverse.tutorials:combinedMarquez cette simulation dans la plateforme « Haply Hub»
Effectuer un étalonnage avant le démarrage
  • Laissez l'Inverse3 e s'étalonner automatiquement (ou posez le stylet sur l'Inkwell et attendez que la LED reste allumée en permanence).
  • Retirez la poignée de l'encrier.
  • Maintenez la touche A ou B enfoncée et tournez la manette : le curseur se déplace dans la direction indiquée par la manette.

Champs d'état lus​

À partir du cadre 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} — Les booléens
  • (Python, uniquement dans le premier cadre) data.inverse3[0].config.type — sélectionne le rayon pour « Inverse3 » ou Minverse
  • (Python, uniquement dans le premier cadre) data.inverse3[0].status.calibrated — invite l'utilisateur à agir lorsque la valeur est « false »

Envoyer / Recevoir​

Le calcul de la direction à partir du quaternion (rotation de +Y mit R(q)) et la restriction à la sphère relèvent de l'algèbre linéaire classique – voir les fichiers sources. La partie API inverse comprend la procédure d'établissement de la connexion et les données envoyées à chaque cycle set_cursor_position.

Une seule boucle asynchrone. Python lit les deux identifiants de périphérique à partir de la première trame d'état ; la négociation dépend du profil et configure.preset: arm_front_centered au premier set_cursor_position-Appel à.

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 – recherchez-le dans tutorials/06-haply-inverse-combined/ dans le répertoire d'installation du service.

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

Voir aussi : Commandes de contrôle (set_cursor_position) · Types (quaternion, vec3) · Montage et espace de travail (préréglages) · Tutoriel 03 (VG sans fil) · Tutoriel n° 5 (Régulation de position)