Skip to main content
Version: 3.5.x

03. Print Wireless VerseGrip

Same pattern as tutorial 02 but for a Wireless VerseGrip — adds buttons (A/B/C) and battery level to the streamed state.

What you'll learn:

  • Reading wireless-specific state fields: buttons.{a,b,c}, battery_level, hall
  • Using probe_orientation as a standalone-observer keepalive
  • Same first-message-only handshake pattern as tutorial 02

Workflow

  1. Open a WebSocket to ws://localhost:10001 and wait for the first state frame.
  2. Pick the first Wireless VerseGrip's device_id from the wireless_verse_grip array.
  3. Build a request with the session profile and a per-device probe_orientation keepalive.
  4. Send the request, then strip the session field — it's a one-shot handshake.
  5. On every later frame, convert the quaternion to Euler angles and print throttled telemetry including button states and battery level. Resend the keepalive each tick.

Parameters

NameDefaultPurpose
URIws://localhost:10001Simulation channel WebSocket URL
PRINT_EVERY_MS100Console-output throttle
Session profile nameco.haply.inverse.tutorials:print-wireless-verse-gripIdentifies this simulation in Haply Hub
Euler convention

The conversion is intrinsic Z-X-Y (yaw → pitch → roll) in the application frame +X right, +Y forward, +Z up. Do not use glm::eulerAngles — it follows a different convention and will read wrong here. All three language variants implement the same math; see the sources for the formula.

When probe_orientation is actually needed

probe_orientation is only useful when your session doesn't send any command to an Inverse3. As soon as you command an Inverse3 (force, position, torque...), the service automatically streams the paired VerseGrip's orientation in every state frame — no probe needed. Use probe_orientation only for standalone grip-monitoring tools like this tutorial.

State fields read

From data.wireless_verse_grip[0].state:

  • orientationquaternion (w, x, y, z)
  • hall — integer hall-sensor reading
  • buttons.a, buttons.b, buttons.c — booleans
  • battery_level — float (0.0 – 1.0)

Send / receive

Same shape as tutorial 02, just with the wireless_verse_grip device array. The WebSocket loop receives a state frame and sends back the handshake + probe_orientation keepalive; the first outgoing message carries the session profile, every subsequent frame carries only the keepalive.

Single async loop.

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["wireless_verse_grip"][0]["device_id"]
request_msg = {
"session": {"configure": {"profile": {
"name": "co.haply.inverse.tutorials:print-wireless-verse-grip"}}},
"wireless_verse_grip": [{
"device_id": device_id,
"commands": {"probe_orientation": {}} # empty — keepalive
}]
}

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

Source: Python · C++ · C++ Glaze

Related: Tutorial 02 (Wired VG) · Types (quaternion) · Control Commands (probe_orientation) · WebSocket Protocol