Zum Hauptinhalt springen
Version: 3.5.x

05. Positionssteuerung

Bewegt den Inverse3 über set_cursor_position. Das Interaktionsmodell unterscheidet sich je nach Sprache — C++ verwendet einmalige Zufallsziele, Python nutzt eine kontinuierliche, über die Tastatur gesteuerte Bewegung.

Was Sie lernen werden:

  • Verwendung von set_cursor_position für die Positionsregelung
  • Zwei verschiedene Interaktionsmodelle für denselben zugrunde liegenden Befehl
  • Das Ziel an eine Arbeitsbereichskugel binden – Minverse einen kleineren Radius als Inverse3
  • Festlegen einer Arbeitsbereichsvoreinstellung, sodass der Ursprung in der Mitte des Arbeitsbereichs liegt

Arbeitsablauf

C++ (Random-Target-Modell)

  1. Starte einen Hintergrund-Eingabethread, der zeilenweise gepufferte Tastenanschläge liest (n, +, -, q) aus der Standardeingabe.
  2. Öffne den WebSocket. Registriere im ersten Status-Frame den Sitzungsprofil und festlegen configure.preset: arm_front_centered. Erzeuge den ersten Zufallswert innerhalb einer Kugel (Rejection Sampling, Radius 0,08 m).
  3. Bei jedem Tick sende eine set_cursor_position Befehl an das aktuelle Ziel. Der Cursor folgt ihm flüssig – der Dienst begrenzt die Rate und interpoliert.
  4. Wenn der Benutzer etwas eingibt n + ENTER: Der Eingabe-Thread generiert ein neues zufälliges Ziel. + / - Geschwindigkeit anpassen; q beendet.

Python (Hold-to-Move-Modell)

  1. Öffne den WebSocket. Überprüfe im ersten Status-Frame status.calibrated — den Benutzer darauf hinweisen, falls das Gerät noch nicht kalibriert ist.
  2. Lesen config.type um den Arbeitsbereichsradius auszuwählen (minverse = 0,04 m, alle anderen Werte = 0,10 m).
  3. Registrieren Sie die Sitzungsprofil und festlegen configure.preset: arm_front_centered.
  4. Bei jedem Tick: Tastaturstatus abfragen (W/A/S/D/Q/E), aktualisiere die Zielposition um SPEED entlang jeder gedrückten Achse, an die Arbeitsbereichskugel andocken und senden set_cursor_position. R setzt das Ziel auf den Ursprung zurück.

Parameter

NameStandard (C++)Standard (Python)Zweck
workspace_radius / RADIUS_INVERSE30.08 m0.10 m (Inverse3) / 0.04 m (Minverse)Radius der Zielkugel
speed_step / SPEED0.01 / Presse0.00005 m / TickSchritt pro Interaktion
PRINT_EVERY_MS100Telemetrie-Drossel (Python)
Sitzungsprofilco.haply.inverse.tutorials:position-controldasselbeIdentifiziert in Haply
Kalibrierungsprüfung (Python)

Die Python-Variante prüft status.calibrated aus dem ersten Status-Frame und fragt den Benutzer, ob das Gerät noch nicht kalibriert ist. Die C++-Variante geht davon aus, dass die Kalibrierung bereits abgeschlossen ist.

Statusfelder gelesen

  • data.inverse3[0].device_id — zum Erstellen des Befehls
  • data.inverse3[0].state.cursor_position — Telemetrie
  • (Python, nur das erste Bild) data.inverse3[0].config.type — wählt Minverse von Inverse3 Minverse aus
  • (Python, nur das erste Bild) data.inverse3[0].status.calibrated — fordert den Benutzer auf, wenn der Wert „false“ ist

Senden / Empfangen

Kommunikationsablauf

  • C++ führt einen Stdin-Hintergrund-Thread aus, der schreibt std::atomic<float> Ziele; der WebSocket-Thread liest sie bei jedem Tick. Auf n + ENTER: Der Eingabe-Thread generiert ein neues zufälliges Ziel; bei q… beide Threads wurden geschlossen.
  • Python ist ein Single-Thread-Asynchronverfahren – die WebSocket-Schleife fragt bei jedem Tick den Tastaturstatus ab und aktualisiert position direkt.

Die Nutzdaten der Inverse-API sind identisch: Der erste Tick enthält das Sitzungsprofil + configure.preset, nachfolgende Ticks enthalten nur set_cursor_position.

Einzelne asynchrone Schleife. Tastaturabfrage (handle_keys) wird bei jedem Tick inline ausgeführt – ohne Threads. config.type und status.calibrated werden einmalig aus dem ersten Zustandsrahmen gelesen.

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"]
radius = get_workspace_radius(data["inverse3"][0].get("config", {}))
# Handshake: profile + preset (one-shot)
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": device_id,
"configure": {"preset": {"preset": "arm_front_centered"}},
}],
}
else:
# Per tick: update position from keyboard (classic polling, not shown), send command
position = handle_keys(position, radius)
request_msg = {
"inverse3": [{
"device_id": device_id,
"commands": {"set_cursor_position": {"position": position}},
}],
}

await websocket.send(json.dumps(request_msg))

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

Siehe auch: Steuerbefehle (set_cursor_position) · Mount & Arbeitsbereich (Voreinstellungen) · Typen (vec3) · Tutorial 06 (Kombiniert)