メインコンテンツへスキップ

02. VerseGrip の出力

最初に有線で接続されたVerseGripから、姿勢(クォータニオン+Z-X-Yオイラー角)、ホールセンサーのレベル、ボタンの状態を取得して出力します。

このチュートリアルで学べる内容:

  • 状態フレームから quaternion の姿勢を読み取る
  • クォータニオンを、度単位の Z-X-Y オイラー角(+X が右、+Y が前、+Z が上)に変換する
  • スタンドアロンのオブザーバーのキープアライブとして probe_orientation を使用する
  • 最初のメッセージのみを使用したハンドシェイクパターン(チュートリアル01と同じ)

ワークフロー​

  1. ws://localhost:10001 WebSocketを開き、最初のステートフレームを待ちます。
  2. verse_grip 配列の中から、最初に有線接続されたVerseGripの device_id を取得します。
  3. セッションプロファイル と、デバイスごとに probe_orientation 「キープアライブ」(空のオブジェクトに対するコマンドで、状態フレームにグリップの姿勢が継続して反映されるようにする)を含むリクエストを作成します。
  4. リクエストを送信した後、session フィールドを削除します。これは1回限りのハンドシェイクであるためです。
  5. 以降の各フレームごとに、クォータニオンをオイラー角に変換し、出力頻度を制限したテレメトリを出力します。毎ティック、キープアライブを再送信します。

パラメーター​

名前デフォルト用途
URIws://localhost:10001シミュレーションチャネル WebSocket のURL
PRINT_EVERY_MS100コンソール出力の頻度制限
セッションプロファイル名co.haply.inverse.tutorials:print-verse-gripHaply Hub 内でこのシミュレーションを識別します
オイラー角の定義

変換は、アプリケーション座標系 +X right, +Y forward, +Z up における固有の Z-X-Y(ヨー → ピッチ → ロール)です。glm::eulerAngles は使用しないでください。 この関数は別の規約に従っているため、ここでは誤った値が読み取られます。3つの言語版はいずれも同じ計算を実装しています。計算式についてはソースを参照してください。

probe_orientation 実際にそれが必要な場合

probe_orientation が有用なのは、セッションがInverse3にコマンドを一切送信しないこの場合に限ります。Inverse3(力、位置、トルクなど)にコマンドを送信するとすぐに、サービスはペアになっているVerseGripの姿勢を、すべての状態フレームで自動的に配信します。そのため、プローブは不要です。probe_orientation は、このチュートリアルのようなスタンドアロンのグリップ監視ツールでのみ使用してください。

読み取り状態フィールド​

data.verse_grip[0].state 以下から読み取ります:

  • orientation — quaternion(w, x, y, z)
  • hall — ホールセンサーの整数値
  • button — 真偽値
  • transform.rotation — ワークスペースの回転(quaternion)。位置とスケールは、姿勢のみを扱うデバイスには該当しないため、送信されることはありません
部分更新の仕様

transform.rotation は、単位クォータニオン {w:1,x:0,y:0,z:0} と等しい場合は省略されます。読み取り時にはデフォルト値を指定してください。常に受信するには、serialization/explicit_fields を有効にしてください。

送受信​

WebSocket ループ:状態フレームを受信し、ハンドシェイクと probe_orientation キープアライブを構築して送信します。最初の送信メッセージにはセッションプロファイルが含まれ、それ以降のフレームにはキープアライブのみが含まれます。

単一の非同期ループ — recv() → コマンドの構築 → send() → 繰り返し。

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["verse_grip"][0]["device_id"]
request_msg = {
"session": {"configure": {"profile": {
"name": "co.haply.inverse.tutorials:print-verse-grip"}}},
"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

コマンドライン引数(Python)​

Pythonバリアントは、チュートリアル01と同じ2つのフラグを受け付けます:

  • --full — 1行の要約ではなく、生のJSONペイロードを整形して出力します。
  • --query-config — 送信する各ティックにおいて session.force_render_full_state を再送信し、各フレームごとに config ブロック(デバイスタイプ、ファームウェア、マウントの変換など)を含みます。状態の差分だけでなく、毎回完全な情報が送信されます。設定の変更をリアルタイムでデバッグする際に便利です。

両方のフラグは組み合わせて使用できます。C++ バリアントでは、これらのフラグは提供されていません。

SDKインストーラーに同梱

チュートリアル02も、SDKと一緒にローカルにインストールされています。サービスのインストールディレクトリ配下の tutorials/02-haply-inverse-print-verse-grip/ ご確認ください。

出典: Python·C++·C++ Glaze

関連: 型(クォータニオン) ・ 制御コマンド(probe_orientation) ・ WebSocket プロトコル ・ チュートリアル03(Wireless VG)