Passer directement au contenu principal

07. L'aire de jeux de Basis et Mount

Appareil Transformation de montage en le manipulant de manière interactive, etconfigure.basis,configure.preset,configure.mount Cela montre comment ils interagissent sur le fil. Afin de maintenir l'attention sur la commande « configure » lors des opérations interactives, le plancher horizontal a été figé.

Ce que vous apprendrez dans ce tutoriel :

  • Réorganisation de la baseParamètres ("XZY" → (cadre de l'application où l'axe Y est en haut)
  • Préréglages(arm_front) et la compréhension de ce que cela permet de configurer
  • Remplacement d'un montage à l'exécution à l'aide de quaternions de rotation (à l'aide du clavier)
  • Règle d'exclusivité : mount et preset est, le même configuration de l'appareil Ils ne peuvent pas coexister au sein d'un bloc
  • En une seule prise configure Fonctionnement : à chaque pression sur la touche, un seul message « configure » est envoyé.
  • (C++ Glaze)std::optional Modélisation de champs exclusifs à l'aide de

Flux de travail​

  1. Dans le premier message,Profil de session,configure.basis: "XZY",configure.preset: arm_front Je l'envoie. Pour un sol fixe, set_cursor_force Commence l'envoi de.
  2. À chaque tick, on lit la coordonnée Y du curseur, etforce_y = max(0, (floor_pos - y) * stiffness) Nous le calculons et l'envoyons.
  3. Lorsque l'utilisateur appuie sur la touche de rotation de la monture,pending_configure = true active le drapeau.
  4. Au prochain tick,configure.mount Construire un bloc. La transformation de ce dernier rotation Il s'agit d'un quaternion unitaire (obtenu en combinant, à partir des angles de tangage et de lacet actuels, d'abord l'axe Z, puis l'axe X).preset Je l'omets. En effet, ces deux éléments sont incompatibles sur le câble.
  5. Touche de réinitialisation (R) pour annuler la substitution. Lors de la prochaine exécution de `configure`, il faudra à nouveau preset est utilisé.

Paramètres​

Nomvaleur par défautUtilisation
BASIS"XZY"Réorganisation des axes — Cadre d'application avec l'axe Y en haut
DEVICE_PRESET / DEVICE_CONFIG_PRESET"arm_front"Préréglages nommés — Le point d'origine correspond à la base de l'appareil
FLOOR_POS_Y0.0 mPlan du plancher fixe (axe Y de l'application)
STIFFNESS1000 N/mConstante de ressort du lit
MOUNT_STEP_DEG10°Angle de rotation par pression sur une touche
PRINT_EVERY_MS200Intervalle d'échantillonnage de la télémétrie

Opération​

CléFonctionnement
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 — Rétablir les préréglages
HAfficher les instructions d'utilisation
QFin
mount et preset Il n'est pas possible de les spécifier simultanément.

Le service comprend les deux configuration de l'appareil Refuser le bloc. Si l'utilisateur remplace le montage, dans ce tutoriel, à partir de toutes les commandes `configure` suivantes, preset est omis.R Si vous appuyez sur cette touche, lors de la prochaine commande « configure », preset est à nouveau active, etmount sera supprimé.

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

La variante C++ lit les entrées ligne par ligne dans un thread stdin s'exécutant en arrière-plan (en appuyant sur la touche Entrée après chaque caractère). Python, quant à lui, récupère les saisies au clavier en temps réel dans la boucle asynchrone principale, c'est pourquoikeyboard Utilisez le paquet. Il n'est pas nécessaire d'appuyer sur ENTER. Les touches et les commandes sont les mêmes.

Champ d'état de lecture​

data.inverse3[i].state Extrait de :

  • cursor_position.y — vec3。Il sert à calculer la profondeur de pénétration dans le sol.
  • current_cursor_force — Ces données sont transmises à des fins de télémétrie

Envoi / Réception​

Le format de la charge utile est identique pour toutes les variantes. La différence notable réside dans le fait que chaque implémentation est exclusive. mount / preset Il s'agit de savoir comment mettre en place cette branche, et comment le thread d'entrée peut informer le thread WebSocket.

keyboard Il s'agit d'une boucle asynchrone unique qui interroge les entrées clavier en temps réel au sein du package.pending_configure est un indicateur global défini par le gestionnaire de touches, etconfigure Il est effacé à chaque fois qu'un 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. Dans le répertoire d'installation du service, sous tutorials/07-haply-inverse-basis-and-mount/ Veuillez vérifier.

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

Voir aussi : Réorganisation de la base · Support et espace de travail · Paramètres de l'appareil · Commandes de contrôle (set_cursor_force) · Type (transform) · Tutoriel 04 (Hello Floor)