Skip to main content
Version : 3.5.x

07. Aire de jeux Basis & Mount

Contrôle de manière interactive l'appareil transformation de montage et montre comment configure.basis, configure.presetet configure.mount travailler ensemble sur le fil. Cela permet de conserver une barre d'état horizontale fixe afin que l'attention reste concentrée sur les commandes de configuration.

Ce que vous apprendrez :

  • Définir un permutation de base ("XZY" → Cadre de fixation Y-up)
  • Choisir un préréglage (arm_front) et comprendre ce qu'il configure
  • Remplacer la configuration de la monture à l'exécution par un quaternion de rotation (à l'aide du clavier)
  • La règle d'exclusion mutuelle : mount et preset ne peuvent pas coexister dans le même configuration de l'appareil bloc
  • One-shot configure semantique : chaque pression sur une touche envoie exactement un message de configuration
  • (C++ Glaze) Modélisation de champs mutuellement exclusifs avec std::optional

Flux de travail

  1. Au premier message : envoyer le profil de session, configure.basis: "XZY"et configure.preset: arm_front. Commencer à envoyer set_cursor_force pour le plancher fixe.
  2. À chaque tick : lire la coordonnée Y du curseur, calculer force_y = max(0, (floor_pos - y) * stiffness), envoyez-le.
  3. Lorsque l'utilisateur appuie sur une touche de rotation de la monture, drapeau pending_configure = true.
  4. Au prochain tick : créer un configure.mount bloc avec une transformation dont rotation est un quaternion unitaire (composition Z puis X de l'inclinaison et du lacet actuels). Omettre preset — les deux sont incompatibles sur le réseau.
  5. Touche de réinitialisation (R) annule la redéfinition ; la configuration suivante revient à preset encore une fois.

Paramètres

NomPar défautObjectif
BASIS"XZY"Permutation d'axes — Cadre d'application Y-up
DEVICE_PRESET / DEVICE_CONFIG_PRESET"arm_front"Préréglage nommé — origine à la base de l'appareil
FLOOR_POS_Y0.0 mPlan de sol fixe (application Y)
STIFFNESS1000 N/mConstante de ressort au sol
MOUNT_STEP_DEG10°Rotation par pression sur une touche
PRINT_EVERY_MS200Manette de télémétrie

Commandes

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

Le service rejette un configuration de l'appareil bloc contenant les deux. Une fois que l'utilisateur a remplacé le montage, le tutoriel omet preset à chaque exécution ultérieure de configure. En appuyant sur R réactive preset lors de la prochaine configuration et des suppressions mount.

Différents modèles d'entrée

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 keyboard Bibliothèque permettant l'interrogation des touches en temps réel dans la boucle asynchrone principale — aucune pression sur la touche Entrée n'est nécessaire. Mêmes touches, mêmes commandes.

Champs d'état lus

De data.inverse3[i].state:

  • cursor_position.yvec3, utilisé pour calculer la pénétration dans le sol
  • current_cursor_force — transmis par télémétrie

Envoyer / recevoir

La structure de la charge utile est identique pour toutes les variantes ; ce qui est intéressant, ce sont les différences dans la manière dont chacune construit les éléments mutuellement exclusifs mount / preset la ramification et la manière dont le thread d'entrée envoie un signal au thread WebSocket.

Boucle asynchrone unique avec interrogation des touches en temps réel via le keyboard paquet. pending_configure est un indicateur global activé par les gestionnaires de clés 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))

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

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