Zum Hauptinhalt springen

01. Inverse3 ausgeben

Verbindet sich mit der Simulation WebSocket und streamt Cursorposition, Geschwindigkeit und Kraft des ersten Inverse3, den der Dienst meldet.

Lerninhalte:

  • Öffnen einer WebSocket-Verbindung und Empfangen der initialen Vollzustandsnachricht
  • Senden eines Keepalive mit Kraft null über set_cursor_force, damit die Sitzung aktiv bleibt
  • Registrieren eines Sitzungsprofils, damit Haply Hub Ihre Simulation erkennt
  • Das Handshake-Muster für die erste Nachricht — session/configure nach dem ersten Senden entfernen
  • Auslesen des Workspace-transform (Position, Rotation, Skalierung) mit der Semantik für Teilaktualisierungen
  • Drosseln der Konsolenausgabe auf eine gut lesbare Rate

Ablauf​

  1. Verbinden Sie sich über WebSocket mit ws://localhost:10001. Der Dienst sendet sofort einen Vollzustands-Frame mit den verbundenen Geräten.
  2. Wählen Sie beim ersten Frame die device_id des ersten Inverse3 aus und erstellen Sie eine Anfragenachricht mit zwei Teilen:
    • session.configure.profile.name — registriert die Simulation bei Haply Hub.
    • Ein gerätespezifischer Befehl set_cursor_force mit einem Nullvektor. Der Dienst verwendet diesen als Keepalive — er sendet so lange Zustands-Frames, wie weiterhin Befehle eingehen.
  3. Senden Sie die Nachricht zurück. Entfernen Sie das Feld session vor dem nächsten Takt — das Sitzungsprofil ist ein einmaliger Handshake; nachfolgende Takte senden nur den Befehl.
  4. Geben Sie bei jedem weiteren Zustands-Frame die Cursor-Felder vec3 (Position, Geschwindigkeit, Kraft) aus, gedrosselt auf etwa 10 Hz, und senden Sie das Keepalive mit Kraft null erneut.

Parameter​

NameStandardwertZweck
URIws://localhost:10001URL des Simulationskanals WebSocket
PRINT_EVERY_MS100Drosselung der Konsolenausgabe
Name des Sitzungsprofilsco.haply.inverse.tutorials:print-inverse3Identifiziert diese Simulation in Haply Hub

Gelesene Zustandsfelder​

Aus data.inverse3[0].state:

  • cursor_position, cursor_velocity, current_cursor_force — jeweils vec3
  • transform — Workspace-Transformation; Unterobjekt mit position (vec3), rotation (quaternion), scale (vec3)
Semantik für Teilaktualisierungen

Unterfelder, die dem neutralen Standardwert entsprechen (position: {0,0,0}, rotation: {w:1,x:0,y:0,z:0}, scale: {1,1,1}), werden aus der Nutzlast weggelassen, um Bandbreite zu sparen. Geben Sie beim Lesen immer einen Standardwert an (z. B. .value("position", default_pos) in C++, .get("position", default_pos) in Python). Aktivieren Sie serialization/explicit_fields, um immer jedes Feld zu erhalten.

Senden / Empfangen​

Die WebSocket-Schleife: Empfangen eines Zustands-Frames, Erstellen und Zurücksenden eines Befehls-Frames. Der erste Befehls-Frame enthält den Sitzungs-Handshake und ein Keepalive mit Kraft null über set_cursor_force; jeder weitere Frame enthält nur das Keepalive (die Sitzung wird entfernt).

Einzelne asynchrone Schleife — recv() → Befehl erstellen → send() → wiederholen.

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"]
request_msg = {
"session": {"configure": {"profile": {
"name": "co.haply.inverse.tutorials:print-inverse3"}}},
"inverse3": [{
"device_id": device_id,
"commands": {"set_cursor_force":
{"vector": {"x": 0.0, "y": 0.0, "z": 0.0}}},
}]
}

await websocket.send(json.dumps(request_msg))
request_msg.pop("session", None) # one-shot handshake

Kommandozeilen-Flags (Python)​

Die Python-Variante akzeptiert zwei Flags, mit denen sich ändern lässt, was das Tutorial ausgibt:

FlagWirkung
--fullGibt die rohe JSON-Nutzlast jedes Zustands-Frames formatiert aus, anstelle der einzeiligen Zusammenfassung. Nützlich, um zu erkennen, welche Felder der Dienst ausgibt.
--query-configFügt bei jedem ausgehenden Takt erneut session.force_render_full_state: {} ein, damit der Dienst bei jedem Frame einen vollständigen Snapshot erneut ausgibt (einschließlich des config-Blocks — Gerätetyp, Firmware, Preset, Halterung, Filter, …). Ohne dieses Flag wird config nur im ersten Frame übermittelt; nachfolgende Frames sind Streaming-Deltas.

Beide Flags lassen sich kombinieren — python 01-haply-inverse-print-inverse3.py --full --query-config gibt eine vollständige JSON-Nutzlast aus, bei der config bei jedem Takt sichtbar ist. Das ist praktisch, wenn Sie live verfolgen, wie sich Einstellungen über Haply Hub oder die HTTP-API ändern. Siehe session.force_render_full_state für den zugrunde liegenden WebSocket-Befehl.

Die C++-Varianten bieten diese Flags nicht an — sie geben immer die einzeilige Zusammenfassung aus und erhalten config nur im ersten Frame.

Im SDK-Installer enthalten

Tutorial 01 ist außerdem lokal mit dem SDK installiert — sehen Sie im Installationsverzeichnis des Dienstes unter tutorials/01-haply-inverse-print-inverse3/ nach.

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

Verwandt: WebSocket Protokoll · Steuerbefehle (set_cursor_force) · Sitzungen · Typen (vec3)