Zum Hauptinhalt springen

04. Hallo Boden

Ihr erster haptischer Effekt: ein virtueller horizontaler Boden, der zurückdrückt, sobald der Cursor in ihn eindringt. Die Kraft ist eine einfache Penalty-Feder (stiffness × penetration_depth), die entlang der Z-Achse über set_cursor_force angewendet wird.

Was Sie lernen:

  • Verwendung von set_cursor_force, um eine Penalty-Federkraft anzuwenden
  • Auslesen von cursor_position und Berechnen der Kraft in Echtzeit
  • (Python) Festlegen eines Presets für den Arbeitsbereich (arm_front_centered), sodass der Ursprung in der Mitte des Arbeitsbereichs liegt
  • (Python) Interaktive Feinabstimmung von Bodenhöhe und Steifigkeit per Tastatur über das Paket keyboard

Ablauf​

  1. Öffnen Sie eine WebSocket-Verbindung zu ws://localhost:10001 und warten Sie auf den ersten Zustandsframe.
  2. Registrieren Sie beim ersten Frame das Session-Profil. Die Variante Python sendet zusätzlich configure.preset: arm_front_centered, sodass der Ursprung in der Mitte des Arbeitsbereichs liegt; die Varianten C++ verwenden die Konfiguration, die auf dem Gerät bereits aktiv ist.
  3. Bei jedem Frame lesen Sie cursor_position.z aus, berechnen force_z = max(0, (floor_pos - z) * stiffness) und senden das Ergebnis als Befehl set_cursor_force zurück.
  4. Bei den folgenden Ticks wird nur noch der Kraftbefehl gesendet – das Session-Profil ist ein einmaliger Handshake.
  5. (Python) Bei jedem Tick werden außerdem die Pfeiltasten der Tastatur abgefragt, und floor_pos / stiffness werden live aktualisiert.

Parameter​

NameStandardZweck
floor_pos0.10 mZ-Koordinate der virtuellen Bodenebene
stiffness1000 N/mFederkonstante (1 mm Eindringtiefe → 1 N)
PRINT_EVERY_MS100–200Drosselung der Telemetrie
Name des Session-Profilsco.haply.inverse.tutorials:hello-floorKennzeichnet diese Simulation in Haply Hub
Interaktiv (nur Python)

Die Variante Python verwendet das Paket keyboard (auf Linux sind erhöhte Berechtigungen erforderlich):

  • ↑ / ↓ — Bodenebene anheben / absenken
  • ← / → — Steifigkeit verringern / erhöhen
  • R — auf Standardwerte zurücksetzen
Erweiterung der Kraft

Kräfte sind beim Dienst-Tick additiv – sie werden aus allen Quellen summiert, bevor sie an das Gerät gesendet werden. Ein Tutorial wie dieses kann neben anderen Kraftquellen bestehen, ohne dass eine der beiden die andere blockiert.

Gelesene Zustandsfelder​

Aus data.inverse3[i].state:

  • cursor_position.z — vec3, wird zur Berechnung der Eindringtiefe verwendet
  • current_cursor_force — wird für die Telemetrie gemeldet

Senden / Empfangen​

Bei jedem Tick: Z-Wert des Cursors auslesen, force_z = max(0, (floor_pos - z) * stiffness) berechnen und einen Befehl set_cursor_force senden. Die erste ausgehende Nachricht enthält außerdem das Session-Profil (alle Varianten) und bei Python zusätzlich configure.preset: arm_front_centered.

Eine einzige asynchrone Schleife. Der Handshake beim ersten Frame enthält Profil und configure.preset, sodass floor_pos = 0.1 mit den Koordinaten der Arbeitsbereichsmitte übereinstimmt.

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"]
# Handshake: profile + preset (one-shot)
request_msg = {
"session": {"configure": {"profile": {"name": "co.haply.inverse.tutorials:hello-floor"}}},
"inverse3": [{
"device_id": device_id,
"configure": {"preset": {"preset": "arm_front_centered"}}
}]
}
else:
# Per tick: compute force along Z, send set_cursor_force
z = data["inverse3"][0]["state"]["cursor_position"]["z"]
force_z = 0.0 if z > floor_pos else (floor_pos - z) * stiffness
request_msg = {
"inverse3": [{
"device_id": device_id,
"commands": {"set_cursor_force":
{"vector": {"x": 0.0, "y": 0.0, "z": force_z}}}
}]
}

await websocket.send(json.dumps(request_msg))
Mitgeliefert mit dem SDK-Installer

Tutorial 04 wird außerdem lokal mit dem SDK installiert – zu finden unter tutorials/04-haply-inverse-hello-floor/ im Installationsverzeichnis des Dienstes.

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

Verwandte Themen: Steuerbefehle (set_cursor_force) · Montage & Arbeitsbereich (Presets) · Typen (vec3) · Sitzungen · Tutorial 07 (Basis & Montage)