Zum Hauptinhalt springen

06. Kombiniert (Inverse3 + Wireless VerseGrip)

Tutorial mit zwei Geräten: Richten Sie den Griff aus und halten Sie eine Taste gedrückt, um den Cursor von Inverse3 in diese Richtung zu bewegen. Der Cursor wird innerhalb eines kugelförmigen Arbeitsraums begrenzt.

Was Sie lernen:

  • Auslesen von zwei Gerätetypen aus demselben Zustandsrahmen (inverse3 und wireless_verse_grip)
  • Ermitteln der Zeigerichtung des Griffs aus seinem Quaternion (lokale +Y-Achse)
  • Verwenden von set_cursor_position, um den Cursor zu einem berechneten Ziel zu bewegen
  • Begrenzen des Zielpunkts auf eine sichere Arbeitsraumkugel – Minverse verwendet einen kleineren Radius als Inverse3
  • Festlegen eines Arbeitsraum-Presets (arm_front_centered), damit der Ursprung in der Mitte der Reichweite liegt

Ablauf​

  1. Beide Geräte erkennen:
    • C++-Varianten fragen beim Start über HTTP GET /devices ab, geben dann eine Kalibrierungsaufforderung aus und warten auf ENTER.
    • Python liest beide Geräte-IDs aus dem ersten Zustandsrahmen von WebSocket.
  2. Registrieren Sie das Sitzungsprofil und setzen Sie in der ersten Nachricht configure.preset: arm_front_centered (einmaliger Handshake).
  3. Bei jedem Zyklus: Lesen Sie die orientation des Griffs und den Zustand von buttons.{a, b}.
  4. Wird eine Bewegungstaste gehalten, berechnen Sie die Richtung des Griffs im Weltkoordinatensystem (R(q) · ĵ – die gedrehte Einheitsachse +Y) und addieren Sie diese, skaliert mit SPEED, zur Zielposition.
  5. Begrenzen Sie den Zielpunkt innerhalb der Arbeitsraumkugel und senden Sie ihn über set_cursor_position.
  6. (nur Python) Passen Sie den Kugelradius anhand von config.type des Geräts an – minverse = 0.04 m, alle anderen = 0.10 m.

Parameter​

NameStandardwertZweck
SPEED0.01 m/tickSchrittweite, solange eine Taste gehalten wird
RADIUS_INVERSE30.10 mBegrenzungsradius des Arbeitsraums für Inverse3 / Inverse3x
RADIUS_MINVERSE0.04 mBegrenzungsradius des Arbeitsraums für Minverse (nur Python – C++ ist fest auf 0.10 codiert)
PRINT_EVERY_MS200Drosselung der Telemetrie
Name des Sitzungsprofilsco.haply.inverse.tutorials:combinedKennzeichnet diese Simulation in Haply Hub
Vor dem Start kalibrieren
  • Lassen Sie Inverse3 sich selbst kalibrieren (oder legen Sie den Griff auf das Inkwell und warten Sie, bis die LED dauerhaft leuchtet).
  • Nehmen Sie den Griff vom Inkwell ab.
  • Halten Sie A oder B gedrückt und drehen Sie den Griff – der Cursor bewegt sich in die Richtung, in die der Griff zeigt.

Gelesene Zustandsfelder​

Aus dem Zustandsrahmen jedes Zyklus:

  • data.inverse3[0].state.cursor_position — vec3
  • data.wireless_verse_grip[0].state.orientation — quaternion
  • data.wireless_verse_grip[0].state.buttons.{a, b, c} — Booleans
  • (Python, nur im ersten Rahmen) data.inverse3[0].config.type — wählt den Radius für Inverse3 oder Minverse
  • (Python, nur im ersten Rahmen) data.inverse3[0].status.calibrated — fordert den Benutzer auf, wenn der Wert false ist

Senden / Empfangen​

Die Berechnung der Richtung aus dem Quaternion (Drehung von +Y mit R(q)) und die Begrenzung auf die Kugel sind klassische lineare Algebra – siehe die Quelldateien. Die Inverse-API-Seite besteht aus dem Handshake und dem pro Zyklus gesendeten set_cursor_position.

Eine einzige asynchrone Schleife. Python liest beide Geräte-IDs aus dem ersten Zustandsrahmen; der Handshake hängt Profil und configure.preset: arm_front_centered an den ersten set_cursor_position-Aufruf an.

async with websockets.connect(URI) as websocket:
while True:
msg = await websocket.recv()
data = json.loads(msg)

if first_message:
first_message = False
inverse3_id = data["inverse3"][0]["device_id"]
grip_id = data["wireless_verse_grip"][0]["device_id"]
radius = get_workspace_radius(data["inverse3"][0].get("config", {}))

# Handshake: profile + preset + first position command
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": inverse3_id,
"configure": {"preset": {"preset": "arm_front_centered"}},
"commands": {"set_cursor_position": {"position": position}},
}],
}
else:
# Per tick: update position from grip pointing direction (classic math, not shown), send
request_msg = {
"inverse3": [{
"device_id": inverse3_id,
"commands": {"set_cursor_position": {"position": position}},
}],
}

await websocket.send(json.dumps(request_msg))
Im SDK-Installer enthalten

Tutorial 06 wird zusätzlich lokal mit dem SDK installiert – suchen Sie in tutorials/06-haply-inverse-combined/ im Installationsverzeichnis des Dienstes.

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

Siehe auch: Steuerbefehle (set_cursor_position) · Typen (quaternion, vec3) · Montage & Arbeitsraum (Presets) · Tutorial 03 (Wireless VG) · Tutorial 05 (Positionsregelung)