Zum Hauptinhalt springen

01. „ Inverse3 “ ausgeben

Stellt eine Verbindung zum WebSocket der Simulation her und überträgt die Cursorposition, Geschwindigkeit und Kraft des ersten „ Inverse3 “, den der Dienst meldet.

Lerninhalte:

  • Öffnen einer WebSocket-Verbindung und Empfangen der ersten Vollzustandsnachricht
  • Senden eines Keepalive mit Stärke 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 Arbeitsbereichs-transform (Position, Drehung, Skalierung) mit der Semantik für Teilaktualisierungen
  • Begrenzung der Konsolenausgabe auf eine gut lesbare Rate

Ablauf​

  1. Stellen Sie über WebSocket eine Verbindung her mit ws://localhost:10001. Der Dienst sendet sofort eine Vollzustands-Frame mit den verbundenen Geräten.
  2. Wählen Sie beim ersten Frame die device_id Wählen Sie den ersten „ Inverse3 “ aus und erstellen Sie eine Anfrage 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 nutzt diesen als Keepalive – er sendet so lange Status-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; in den folgenden Takten wird nur der Befehl gesendet.
  4. Geben Sie bei jedem weiteren Zustands-Frame die Cursor-Felder ein vec3 (Position, Geschwindigkeit, Kraft), gedrosselt auf etwa 10 Hz, und senden Sie das Keepalive mit Kraft null erneut.

Parameter​

NameStandardwertZweck
URIws://localhost:10001URL des WebSocket-Simulationskanals
PRINT_EVERY_MS100Drosselung der Konsolenausgabe
Name des Sitzungsprofilsco.haply.inverse.tutorials:print-inverse3Diese Simulation ist im „ Haply Hub“ zu finden.

Ausgelesene Zustandsfelder​

Aus data.inverse3[0].state:

  • cursor_position, cursor_velocity, current_cursor_force — jeweils vec3
  • transform — Arbeitsbereichstransformation; 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 stets jedes Feld zu erhalten.

Senden / Empfangen​

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

Eine 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

Befehlszeilenoptionen (Python)​

Die Python-Variante akzeptiert zwei Flags, mit denen sich die Ausgabe des Tutorials anpassen lässt:

FlaggeWirkung
--fullGibt die rohe JSON-Nutzlast jedes Status-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 ein session.force_render_full_state: {} ein, damit der Dienst bei jedem Frame erneut einen vollständigen Snapshot ausgibt (einschließlich des config-Blöcke — Gerätetyp, Firmware, Voreinstellung, Halterung, Filter, …). Ohne dieses Flag wird config wird nur im ersten Frame übertragen; nachfolgende Frames sind Streaming-Deltas.

Beide Flaggen 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 möchten, wie sich Einstellungen über den „ 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-Installationsprogramm 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

Verwandte Themen: WebSocket-Protokoll · Steuerbefehle (set_cursor_force) · Sitzungen · Typ (vec3)