Zum Hauptinhalt springen
Version: 3.5.x

07. Basis & Mount Spielplatz

Steuert das Gerät interaktiv Montage-Transformation und zeigt, wie configure.basis, configure.presetund configure.mount Gemeinsam am Befehlszeilen-Interpreter arbeiten. Es wird eine feste horizontale Zeile beibehalten, damit der interaktive Fokus auf den Konfigurationsbefehlen bleibt.

Was Sie lernen werden:

  • Festlegen einer Basispermutation ("XZY" → Y-up-Anwendungsrahmen)
  • Die Wahl eines Voreinstellung (arm_front) und zu verstehen, was damit konfiguriert wird
  • Das Reittier zur Laufzeit durch ein Rotationsquaternion überschreiben (über die Tastatur)
  • Die Regel des gegenseitigen Ausschlusses: mount und preset können nicht nebeneinander existieren Gerät konfigurieren Block
  • Einmalig configure Semantik: Jeder Tastendruck löst genau eine Konfigurationsnachricht aus
  • (C++ Glaze) Modellierung von sich gegenseitig ausschließenden Feldern mit std::optional

Arbeitsablauf

  1. Bei der ersten Nachricht: sende die Sitzungsprofil, configure.basis: "XZY"und configure.preset: arm_front. Mit dem Senden beginnen set_cursor_force für den festen Boden.
  2. Bei jedem Tick: Y-Koordinate des Cursors lesen, berechnen force_y = max(0, (floor_pos - y) * stiffness), schick es.
  3. Wenn der Benutzer eine Taste zur Drehung der Halterung drückt, wird das Flag gesetzt pending_configure = true.
  4. Beim nächsten Takt: Erstelle eine configure.mount Block mit einer Transformation, deren rotation ist ein Einheitsquaternion (Z-dann-X-Komposition der aktuellen Nick- und Gierwinkel). Weglassen preset — Die beiden schließen sich im Netzwerk gegenseitig aus.
  5. Reset-Taste (R) hebt die Überschreibung auf; bei der nächsten Konfiguration wird auf preset wieder.

Parameter

NameStandardZweck
BASIS"XZY"Achsenpermutation – Y-up-Anwendungsrahmen
DEVICE_PRESET / DEVICE_CONFIG_PRESET"arm_front"Benannte Voreinstellung – Ursprung am Gerätefuß
FLOOR_POS_Y0.0 mFeste Bodenebene (Anwendung Y)
STIFFNESS1000 k. A.Bodenfederkonstante
MOUNT_STEP_DEG10°Drehung pro Tastendruck
PRINT_EVERY_MS200Telemetrie-Drosselklappe

Bedienelemente

SchlüsselAktion
W / SHalterung um ±10° um die +X-Achse des Geräts drehen (Neigung)
A / DHalterung um ±10° um die +Z-Achse des Geräts drehen (Gieren)
RMontage zurücksetzen – auf Voreinstellung zurücksetzen
HSteuerelemente anzeigen
QBeenden
mount und preset schließen sich gegenseitig aus

Der Dienst lehnt eine Gerät konfigurieren Block, der beides enthält. Sobald der Benutzer die Einbindung überschreibt, lässt das Tutorial preset bei jedem weiteren Konfigurationsvorgang. Durch Drücken der R wieder aktivieren preset bei den nächsten Konfigurationen und Löschvorgängen mount.

Verschiedene Eingabemodelle

Die C++-Varianten lesen zeilenbasierte Eingaben in einem Stdin-Hintergrundthread ein (drücken Sie nach jedem Buchstaben die Eingabetaste). Python verwendet die keyboard Paket für die Echtzeit-Tastenabfrage in der asynchronen Hauptschleife – kein ENTER-Tastenanschlag erforderlich. Gleiche Tasten, gleiche Befehle.

Statusfelder gelesen

Von data.inverse3[i].state:

  • cursor_position.yvec3, zur Berechnung der Durchdringung des Bodens
  • current_cursor_force — für die Telemetrie gemeldet

Senden / Empfangen

Die Form der Nutzlast ist bei allen Varianten gleich; interessant sind die Unterschiede darin, wie jede Variante die sich gegenseitig ausschließenden mount / preset Verzweigungen und wie der Eingabe-Thread dem WebSocket-Thread Signale sendet.

Einzelne asynchrone Schleife mit Echtzeit-Tastenabfrage über die keyboard Paket. pending_configure ist ein globales Flag, das von den Schlüssel-Handlern gesetzt und bei jedem configure Der Block wird gesendet.

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))

Quelle: Python · C++ · C++ Glaze

Siehe auch: Basispermutation · Halterung & Arbeitsbereich · Gerätekonfiguration · Steuerbefehle (set_cursor_force) · Typen (transformieren) · Tutorial 04 (Hallo Boden)