Zum Haupttext springen

05. Positionssteuerung

set_cursor_positionÜber Inverse3 wird der Cursor in Richtung der Zielposition bewegt. Das Interaktionsmodell hängt von der jeweiligen Sprache ab. C++ verwendet einmalig zufällig ausgewählte Ziele, während Python eine Methode nutzt, bei der die Bewegung kontinuierlich über die Tastatur gesteuert wird.

Lerninhalte:

  • Zur Steuerung des Positionsmodus set_cursor_position Anleitung
  • Zwei Interaktionsmodelle für denselben Basisbefehl
  • Die Zielposition auf den Arbeitsbereich (Kugel) beschränken (Clamping) — Minverse verwendet einen kleineren Radius als Inverse3
  • Arbeitsbereich-Voreinstellungen so festlegen, dass der Ursprung in der Mitte des Arbeitsbereichs liegt

Workflow​

C++ (Modell mit zufälligen Zielen)​

  1. Tastatureingaben, die zeilenweise über stdin eingegeben werden (n, +, -, q) startet einen Hintergrund-Eingabe-Thread zum Lesen.
  2. WebSocket wird geöffnet. Im ersten Status-Frame Sitzungsprofilregistrieren und configure.preset: arm_front_centeredwird festgelegt. Innerhalb der Kugel wird ein erstes zufälliges Ziel erzeugt (Rejection Sampling, Radius 0,08 m).
  3. Bei jedem Schritt in Bezug auf das aktuelle Ziel set_cursor_position Der Befehl wird gesendet. Der Cursor folgt dem Ziel sanft – der Dienst begrenzt die Übertragungsrate (Rate-Limit) und führt eine Interpolation durch.
  4. Der Benutzer n Wenn Sie nach der Eingabe die ENTER-Taste drücken, generiert der Eingabe-Thread ein neues zufälliges Ziel. + / -um die Geschwindigkeit anzupassen und, qund endet mit.

Python (Druck-Bewegungs-Modell)​

  1. WebSocket wird geöffnet. Im ersten Status-Frame status.calibratedüberprüft und benachrichtigt den Benutzer, falls das Gerät noch nicht kalibriert wurde.
  2. config.typeLesen Sie die Anleitung und wählen Sie den Arbeitsbereichsradius aus (minverse = 0,04 m, ansonsten = 0,10 m).
  3. Sitzungsprofilregistrieren und configure.preset: arm_front_centeredein.
  4. Bei jedem Tastenanschlag wird der Tastaturstatus (W/A/S/D/Q/E) abfragen und entlang jeder gedrückten Achse SPEEDNachdem die Zielposition entsprechend aktualisiert wurde, wird sie in den Arbeitsbereich eingeklemmt und set_cursor_positionübermittelt. RWenn Sie darauf klicken, wird das Ziel auf den Ausgangspunkt zurückgesetzt.

Parameter​

NameStandardwert (C++)Standardwert (Python)Verwendungszweck
workspace_radius / RADIUS_INVERSE30.08 m0.10 m (Inverse3) / 0.04 m (Minverse)Radius des Zielkreises
speed_step / SPEED0.01 / Drücken0.00005 m / TickBewegungsabstand pro Interaktion
PRINT_EVERY_MS—100Telemetrie-Drosselung (Python)
Sitzungsprofilco.haply.inverse.tutorials:position-controlgleichHaply Wird vom Hub zur Identifizierung verwendet
Kalibrierungsprüfung (Python)

Die Python-Varianten beginnen im ersten Zustandsrahmen status.calibratedüberprüft und benachrichtigt den Benutzer, falls das Gerät nicht kalibriert wurde. Die C++-Variante geht davon aus, dass die Kalibrierung bereits abgeschlossen ist.

Feld „Lesezustand“​

  • data.inverse3[0].device_id — Zur Befehlsgenerierung verwendet
  • data.inverse3[0].state.cursor_position — Telemetrie
  • (Python, nur im ersten Frame) data.inverse3[0].config.type — Inverse3 oder Minverse – Radius auswählen
  • (Python, nur im ersten Frame) data.inverse3[0].status.calibrated — Wenn der Wert „false“ ist, wird der Benutzer benachrichtigt

Senden und Empfangen​

Kommunikationsablauf​

  • **C++** führt einen stdin-Thread im Hintergrund aus, um std::atomic<float> Der Zielwert wird gespeichert, und der WebSocket-Thread liest diesen Wert bei jedem Tick aus. n Wenn Sie nach der Eingabe die ENTER-Taste drücken, generiert der Eingabe-Thread ein neues zufälliges Ziel, und qWenn Sie darauf klicken, werden beide Threads beendet.
  • Pythonist ein single-threaded, asynchrones Verfahren – die WebSocket-Schleife fragt bei jedem Takt den Tastaturstatus ab und positionwird direkt aktualisiert.

Die Inverse-API-Nutzdaten sind identisch. Beim ersten Tick werden das Sitzungsprofil und configure.presetDies ist enthalten, und in den nachfolgenden Ticks set_cursor_position… sind enthalten.

Es handelt sich um eine einzelne asynchrone Schleife. Tastaturabfrage (handle_keys) wird bei jedem Tick inline ausgeführt, ohne dass ein separater Thread verwendet wird. config.typeund status.calibratedwird nur einmal im ersten Status-Frame 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))
einschließlich SDK-Installationsprogramm

Auch Tutorial 05 ist zusammen mit dem SDK lokal installiert. Im Installationsverzeichnis des Dienstes unter tutorials/05-haply-inverse-position-control/können Sie dort nachlesen.

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

Verwandte Dokumente: Steuerbefehl (set_cursor_position) · Mount & Workspace (Voreinstellung) · Typ (vec3) · Tutorial 06 (Kombiniert)