Aller directement au corps du texte

07. Basis & Mount Playground

de l'appareil Conversion des monturesde le contrôler de manière interactive, et configure.basis, configure.preset, configure.mountCela montre comment ils fonctionnent ensemble au niveau du protocole Wire. Le focus interactif reste sur la commande « configure » grâce à un fond horizontal fixe.

Contenu pédagogique :

  • permutation de base Paramètres ("XZY" → (Cadre de l'application : direction vers le haut sur l'axe Y)
  • Préréglages(arm_front) Sélectionner et comprendre le contenu de chaque préréglage
  • Redéfinition du montage à l'exécution à l'aide de quaternions de rotation (basée sur les entrées clavier)
  • Règle d'exclusion mutuelle : mountWa presetcomme l'argent Configuration de l'appareil Ils ne peuvent pas coexister dans un même bloc
  • ponctuel configure Fonctionnement : à chaque pression sur une touche, le message « configure » est envoyé exactement une fois.
  • (C++ Glaze) std::optionalModélisation de champs mutuellement exclusifs à l'aide de

Flux de travail​

  1. Dès que vous recevez le premier message, Profil de session, configure.basis: "XZY", configure.preset: arm_fronttransmet. Pour un sol fixe set_cursor_force La transmission commence.
  2. À chaque tick, lire la valeur Y du curseur et force_y = max(0, (floor_pos - y) * stiffness)est calculée puis transmise.
  3. Lorsque l'utilisateur appuie sur la touche de rotation du support, pending_configure = trueRéglez-le sur .
  4. Au prochain tick, rotationqui contient cette transformation, qui est un quaternion unitaire (composé de Z puis de X pour les angles de tangage et de lacet actuels) configure.mount Constitue un bloc. presetest omis. Ces deux champs sont mutuellement exclusifs sur le câble.
  5. Touche de réinitialisation (R) désactive la redéfinition. Lors de la prochaine configuration, il faudra à nouveau presetutilise.

Paramètres​

NomValeur par défautUtilisation
BASIS"XZY"Permutation des axes — Système de coordonnées orienté vers le haut sur l'axe Y
DEVICE_PRESET / DEVICE_CONFIG_PRESET"arm_front"Préréglages nommés — Point d'origine : socle de l'appareil
FLOOR_POS_Y0.0 mPlan de sol fixe (application Y)
STIFFNESS1000 N/mConstante de ressort du plancher
MOUNT_STEP_DEG10°Angle de rotation par touche enfoncée
PRINT_EVERY_MS200Accélérateur télémétrique

Contrôle​

cléMouvement
W / SFaire pivoter le support de ±10° par rapport à l'axe X (pas) de l'appareil
A / DFaire pivoter le support de ±10° par rapport à l'axe Z (lacet) de l'appareil
RRéinitialisation du montage — Retour aux préréglages
HAffichage des touches de contrôle
QFin
mountWa presetsont mutuellement exclusives

Le service comprend les deux champs Configuration de l'appareil Le bloc est rejeté. Si l'utilisateur redéfinit le montage, le tutoriel, lors de toutes les étapes de configuration suivantes, presetest omis. REn cliquant sur ce bouton, lors de la prochaine configuration, presetcelui-ci est réutilisé et mountsont exclues.

Différences entre les modèles d'entrée

La version C++ lit les entrées ligne par ligne dans un thread stdin s'exécutant en arrière-plan (appuyez sur ENTRÉE après chaque caractère saisi). Python, quant à lui, utilise la boucle asynchrone principale pour keyboard Comme le package interroge les frappes en temps réel, il n'est pas nécessaire d'appuyer sur la touche ENTER. Les touches et les commandes sont identiques.

Champ « État de lecture »​

data.inverse3[i].stateValeur lue à :

  • cursor_position.y — vec3. Il sert à calculer le débit de passage au sol.
  • current_cursor_force — Ces données sont transmises à des fins de télémétrie.

Émission / Réception​

La structure de la charge utile est identique dans toutes les variantes. La différence réside dans le fait que chaque variante est mutuellement exclusive. mount / preset Il s'agit de la manière dont la branche est constituée et de la façon dont le thread d'entrée envoie des signaux au thread WebSocket.

Dans une boucle asynchrone unique, keyboard Le paquet interroge les entrées clavier en temps réel. pending_configureest un indicateur global défini par le gestionnaire de touches, et configure Il est réinitialisé à chaque fois qu'un bloc est transmis.

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"]
# Handshake: profile + basis + preset
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": device_id,
"configure": build_configure_block(first_handshake=True),
# -> {"basis": {"permutation": "XZY"},
# "preset": {"preset": "arm_front"}}
}],
}
else:
handle_key_inputs() # may set pending_configure = True (classic, not shown)

y = data["inverse3"][0]["state"]["cursor_position"]["y"]
force_y = 0.0 if y > FLOOR_POS_Y else (FLOOR_POS_Y - y) * STIFFNESS

entry = {
"device_id": device_id,
"commands": {"set_cursor_force":
{"vector": {"x": 0.0, "y": force_y, "z": 0.0}}},
}
if pending_configure:
entry["configure"] = build_configure_block(first_handshake=False)
# -> {"mount": {...}} OR {"preset": {...}} (never both)
pending_configure = False

request_msg = {"inverse3": [entry]}

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

Le tutoriel 07 est également installé localement avec le SDK. Dans le répertoire d'installation du service, sous tutorials/07-haply-inverse-basis-and-mount/Vous pouvez le trouver ici.

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

Sujets connexes : Permutation de base · Montage et espace de travail · Configuration de l'appareil · Commandes de contrôle (set_cursor_force) · Type (transformation) · Tutoriel n° 4 (Bonjour le sol)