Aller au contenu principal

07. Base et aire de jeux « Mount »

Contrôle de manière interactive la Transformation de montage de l'appareil et explique comment configure.basis, configure.preset et configure.mount interagir au niveau du protocole. Un fond horizontal fixe est conservé afin que l'interaction reste centrée sur les commandes « configure ».

Ce que vous allez apprendre :

  • Définition d'une Permutation de bases ("XZY" → Cadre d'application avec l'axe Y vers le haut)
  • Choix d'un Préréglages (arm_front) et comprendre ce qu'il configure
  • Remplacement du montage à l'exécution par un quaternion de rotation (contrôlé via le clavier)
  • Le principe d'exclusivité réciproque : mount et preset ne peuvent pas figurer ensemble dans le même bloc de la Configuration de l'appareil se produire
  • Unique configure- Semantik : chaque pression sur une touche envoie exactement un message « configure ».
  • (C++ Glaze) Modélisation de champs mutuellement exclusifs avec std::optional

Déroulement​

  1. Pour le premier message : envoyez le Profil de session, configure.basis: "XZY" et configure.preset: arm_front. Commencez par le sol ferme set_cursor_force à envoyer.
  2. À chaque tick : lire la coordonnée Y du curseur, force_y = max(0, (floor_pos - y) * stiffness) calculer et envoyer.
  3. Lorsque l'utilisateur appuie sur une touche de rotation de montage, définissez pending_configure = true.
  4. Au prochain tick, vous créerez un configure.mount-Bloc comportant une transformation dont rotation est un quaternion unitaire (composition Z puis X à partir des valeurs actuelles de tangage et de lacet). Laissez preset weg – ces deux éléments s'excluent mutuellement au niveau du protocole.
  5. Le bouton de réinitialisation (R) annule le remplacement ; la commande « configure » suivante reprend alors preset Retour.

Paramètres​

NomStandardObjet
BASIS"XZY"Permutation des axes — Cadre d'application avec l'axe Y orienté vers le haut
DEVICE_PRESET / DEVICE_CONFIG_PRESET"arm_front"Préréglage nommé — Origine au niveau de la base de l'appareil
FLOOR_POS_Y0.0 mNiveau du sol fixe (Y d'application)
STIFFNESS1000 N/mConstante de Feder du sol
MOUNT_STEP_DEG10°Rotation par simple pression sur une touche
PRINT_EVERY_MS200Limitation de la télémétrie

Commande​

GoûtAction
W / SFaire pivoter l'appareil de ±10° autour de l'axe +X (inclinaison)
A / DFaire pivoter l'appareil de ±10° autour de l'axe +Z (lacet)
RRéinitialiser le montage – Retour au préréglage
HAfficher les commandes
QQuitter
mount et preset s'excluent mutuellement

Le service refuse de bloquer la Configuration de l'appareil ab, qui contient les deux. Dès que l'utilisateur remplace le montage, le tutoriel preset dans chaque instruction « configure » suivante. En appuyant sur R sera preset réactivée lors de la prochaine instruction « configure » et mount rejeté.

Différents modèles de saisie

Les variantes en C++ lisent les entrées ligne par ligne dans un thread « stdin » s'exécutant en arrière-plan (appuyez sur ENTRÉE après chaque lettre). Python utilise le module keyboard pour la détection des touches en temps réel dans la boucle principale asynchrone – il n'est pas nécessaire d'appuyer sur ENTER. Mêmes touches, mêmes commandes.

Champs d'état lus​

Aus data.inverse3[i].state:

  • cursor_position.y — vec3, est utilisé pour calculer la pénétration dans le sol
  • current_cursor_force — est transmis dans le cadre de la télémétrie

Envoyer / Recevoir​

La structure de la charge utile est identique dans toutes les variantes ; ce qui est intéressant, ce sont les différences dans la manière dont chaque variante traite les branches qui s'excluent mutuellement mount / preset et comment le thread d'entrée envoie un signal au thread WebSocket.

Boucle asynchrone unique avec interrogation des touches en temps réel via le paquet keyboard. pending_configure est un indicateur global qui est activé par les gestionnaires de clavier et réinitialisé à chaque fois qu'un configure- Le bloc est envoyé.

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

Le tutoriel 07 est également installé localement avec le SDK – vous le trouverez à l'emplacement suivant : tutorials/07-haply-inverse-basis-and-mount/ dans le répertoire d'installation du service.

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

À lire également : Permutation de bases · Support et espace de travail · Configuration de l'appareil · Commandes de contrôle (set_cursor_force) · Types (transformation) · Tutoriel 04 (Bonjour Floor)