Zum Hauptinhalt springen

05. Positionskontrolle

Bewegen Sie den Cursor „ Inverse3 “ mithilfe von set_cursor_position. Das Interaktionsmodell variiert je nach Sprache — C++ verwendet zufällige Einmalziele, Python nutzt eine kontinuierliche, über die Tastatur gesteuerte Bewegung.

Was Sie lernen werden:

  • Verwenden set_cursor_position für die Regelung im Positionsmodus
  • Zwei verschiedene Interaktionsmodelle für denselben zugrunde liegenden Befehl
  • Die Zielauswahl auf einen Bereich des Arbeitsraums beschränken — Minverse verwendet einen kleineren Radius als Inverse3
  • Eine Arbeitsbereichsvoreinstellung festlegen, damit der Ursprung in der Mitte des Arbeitsbereichs liegt

Arbeitsablauf​

C++ (Zufallszielmodell)​

  1. Starten Sie einen Hintergrund-Thread, der die Tastatureingaben liest, die zeilenweise gepuffert werden (n, +, -, q), von der Standardeingabe (stdin).
  2. Öffnen Sie WebSocket. Speichern Sie beim ersten Status-Frame den Sitzungsprofil und legen Sie fest configure.preset: arm_front_centered. Erzeugen Sie das erste zufällige Ziel innerhalb einer Kugel (Rejection-Sampling, Radius 0,08 m).
  3. Senden Sie bei jedem Zyklus einen Befehl set_cursor_position zum aktuellen Ziel. Der Cursor folgt dem Ziel sanft – der Dienst begrenzt die Datenrate und interpoliert die Positionen.
  4. Wenn der Benutzer Folgendes eingibt n Anschließend ENTRÉE: Der Eingabestrom generiert ein neues zufälliges Ziel. + / - Passen Sie die Geschwindigkeit an; q Beenden.

Python (Modell mit konstanter Verschiebung)​

  1. Öffnen Sie WebSocket. Überprüfen Sie beim ersten Status-Frame, ob status.calibrated — Zeigen Sie dem Benutzer eine Aufforderung an, wenn das Gerät noch nicht kalibriert ist.
  2. Lesen Sie config.type um den Radius des Arbeitsbereichs auszuwählen (minverse = 0,04 m, alle anderen Werte = 0,10 m).
  3. Speichern Sie das Sitzungsprofil und legen Sie fest configure.preset: arm_front_centered.
  4. In jedem Zyklus: den Status der Tastatur abfragen (W/A/S/D/Q/E), verschieben Sie das Ziel von SPEED Entlang jeder eingegebenen Achse beschränken Sie sie auf den Arbeitsbereich und senden Sie dann set_cursor_position. R Setzt das Ziel auf den Ursprung zurück.

Einstellungen​

NomStandardwert (C++)Standardwert (Python)Rolle
workspace_radius / RADIUS_INVERSE30.08 m0.10 m (Inverse3) / 0.04 m (Minverse)Radius der Zielkugel
speed_step / SPEED0.01 / Unterstützung0.00005 m / ZyklusNicht durch Interaktion
PRINT_EVERY_MS—100Einschränkung der Telemetrie (Python)
Sitzungsprofilco.haply.inverse.tutorials:position-controlidentischErmöglicht die Anmeldung bei „ Haply Hub“
Überprüfung der Kalibrierung (Python)

Die Python-Variante überprüft status.calibrated bereits ab dem ersten Status-Frame und zeigt dem Benutzer eine Eingabeaufforderung an, wenn das Gerät nicht kalibriert ist. Die C++-Variante geht davon aus, dass die Kalibrierung bereits erfolgt ist.

Meister der Les-États​

  • data.inverse3[0].device_id — um den Befehl zu erstellen
  • data.inverse3[0].state.cursor_position — Telemetrie
  • (Python, nur erster Rahmen) data.inverse3[0].config.type — legt den zu verwendenden Radius fest: Inverse3 oder Minverse
  • (Python, nur erster Rahmen) data.inverse3[0].status.calibrated — zeigt dem Benutzer eine Eingabeaufforderung an, wenn der Wert falsch ist

Versand und Empfang​

Ablauf der Vorträge​

  • C++ führt einen Hintergrundprozess aus, der die Standardeingabe liest und die Ziele schreibt std::atomic<float> ; der WebSocket-Thread liest sie in jedem Zyklus aus. Auf n Anschließend ENTRÉE: Der Eingabestrom erzeugt ein neues zufälliges Ziel; auf q, da bleiben die beiden Söhne stehen.
  • Python asynchron und monofil – die WebSocket-Schleife fragt in jedem Zyklus den Status der Tastatur ab und aktualisiert position direkt.

Die Nutzdaten der Inverse-API sind identisch: Der erste Durchlauf überträgt das Sitzungsprofil und configure.preset, und die folgenden Zyklen transportieren nur set_cursor_position.

Einzigartige asynchrone Schleife. Die Abfrage der Tastatur (handle_keys) wird bei jedem Durchlauf direkt in der Schleife ausgeführt – ohne separaten Ausführungsfaden. config.type et status.calibrated werden nur einmal gelesen, beginnend mit dem ersten Zustandsrahmen.

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))
Im Lieferumfang des SDK-Installationsprogramms enthalten

Das Tutorial 05 wird ebenfalls lokal mit dem SDK installiert – siehe tutorials/05-haply-inverse-position-control/ im Installationsverzeichnis des Dienstes.

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

Siehe auch: Steuerbefehle (set_cursor_position) · Montage und Arbeitsbereich (Voreinstellungen) · Typen (vec3) · Tutorial 06 (Kombiniert)