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

06. セット(Inverse3 +ワイヤレスVerseGrip)

2つのデバイスを使ったチュートリアル:グリップを特定の方向に向け、ボタンを押し続けると、Inverse3 のカーソルがその方向に移動します。カーソルの移動範囲は球形の作業空間内に制限されています。

学習内容:

  • 同一の状態フレーム内で2種類のデバイスタイプを読み取る(inverse3 和 wireless_verse_grip)
  • グリップの 四元数(局所 +Y (軸)から向きを抽出する
  • 使用 set_cursor_position 計算によって導き出された目標位置にカーソルを移動させる
  • ターゲットを安全な球形の作業空間内に制限する――Minverse で使用される半径は、Inverse3
  • 設定 ワークスペースのプリセット(arm_front_centered),原点を到達可能範囲の中心に位置させる

ワークフロー​

  1. 2台のデバイスが検出されました:
    • 起動時には、C++ の各バリエーションをHTTPクエリを通じて GET /devices,その後、キャリブレーションのメッセージが表示されたら、ENTER キーが押されるのを待ちます。
    • Pythonは、最初の WebSocket ステータスフレームから 2 台のデバイスの ID を読み取ります。
  2. 最初のメッセージで登録する 会話プロファイル,そして設定する configure.preset: arm_front_centered(一度きりの握手)。
  3. 各サイクル:グリップの orientation および buttons.{a, b} 状態。
  4. 運動ボタンを長押しすると、ワールド座標系におけるグリップの方向が計算されます(R(q) · ĵ,すなわち回転後の単位の+Y軸)を指定し、 SPEED 拡大・縮小した後、目的の位置に重ね合わせます。
  5. ターゲットをワークスペースの球体内に制限し、以下の方法で set_cursor_position 送信。
  6. (Pythonのみ)デバイスの config.type 球体の半径を調整する――minverse 0.04 m、その他のすべてのタイプは 0.10 m である。

パラメータ​

名称デフォルト値用途
SPEED0.01 m/周期ボタンを押し続けた場合の1ステップあたりの移動距離
RADIUS_INVERSE30.10 mInverse3 / Inverse3x の作業領域の制限半径
RADIUS_MINVERSE0.04 mMinverse ワークスペースの制限半径(Python のみ適用 —— C++ ではハードコーディングされており、 0.10)
PRINT_EVERY_MS200テレメトリ出力のスロットリング間隔
セッションプロファイル名co.haply.inverse.tutorials:combinedHaply Hub でこのシミュレーションを識別する
実行前にまず校正を行う
  • Inverse3 を自動キャリブレーションさせます(または、グリップをインクカートリッジの上に置き、LEDが点灯したままになるまで待ちます)。
  • インクカートリッジからグリップを取り外してください。
  • A または B を押し続けながらグリップを回すと、カーソルがグリップの向いている方向へ移動します。

読み込まれたステータスフィールド​

各サイクルのステートフレームから読み取る:

  • data.inverse3[0].state.cursor_position — vec3
  • data.wireless_verse_grip[0].state.orientation — quaternion
  • data.wireless_verse_grip[0].state.buttons.{a, b, c} — ブール値
  • (Python、第1フレームのみ)data.inverse3[0].config.type ——Inverse3 またはMinverse の半径を選択するためのもの
  • (Python、第1フレームのみ)data.inverse3[0].status.calibrated —— false の場合、ユーザーにメッセージを表示する

送信 / 受信​

四元数から方向への変換(使用して R(q) 回転 +Y)および球体制限はいずれも古典的な線形代数の演算であり、詳細はソースファイルを参照のこと。Inverse API の部分は、ハンドシェイク手順および各周期の set_cursor_position 呼び出しの構成。

単一の非同期ループ。Python は最初のステートフレームから 2 台のデバイスの ID を読み取ります。ハンドシェイクプロセスでは、設定ファイル + configure.preset: arm_front_centered 初回に追加 set_cursor_position 呼び出し中。

async with websockets.connect(URI) as websocket:
while True:
msg = await websocket.recv()
data = json.loads(msg)

if first_message:
first_message = False
inverse3_id = data["inverse3"][0]["device_id"]
grip_id = data["wireless_verse_grip"][0]["device_id"]
radius = get_workspace_radius(data["inverse3"][0].get("config", {}))

# Handshake: profile + preset + first position command
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": inverse3_id,
"configure": {"preset": {"preset": "arm_front_centered"}},
"commands": {"set_cursor_position": {"position": position}},
}],
}
else:
# Per tick: update position from grip pointing direction (classic math, not shown), send
request_msg = {
"inverse3": [{
"device_id": inverse3_id,
"commands": {"set_cursor_position": {"position": position}},
}],
}

await websocket.send(json.dumps(request_msg))
SDK インストーラーに同梱されています

チュートリアル 06 も SDK とともにローカルにインストールされます。サービスインストールディレクトリ内の tutorials/06-haply-inverse-combined/ 中で探す。

ソースコード: Python·C++·C++ Glaze

関連情報: 制御コマンド(set_cursor_position) ・ 型(quaternion、vec3) ・ インストールとワークスペース(デフォルト設定) ・ チュートリアル 03(ワイヤレス VG) ・ チュートリアル 05(位置制御)