本文へスキップ
バージョン: 3.5.x

05. 位置制御

Inverse3 ターゲット位置に向かって移動させる set_cursor_position. 言語によって相互作用モデルは異なる — C++では単発のランダムなターゲットを使用するのに対し、Pythonではキーボード操作による連続的な移動を使用します。

学習内容:

  • 使用して set_cursor_position 位置制御用
  • 同じ基本コマンドに対する2つの異なるインタラクションモデル
  • ターゲットを作業領域の球体に固定する —Minverse Inverse3よりも半径を小さくMinverse
  • ワークスペースのプリセットを設定し、原点をワークスペースの中心に配置する

ワークフロー

C++(ランダムターゲットモデル)

  1. 行単位でバッファリングされたキー入力を読み込むバックグラウンド入力スレッドを開始する(n, +, -, q) を標準入力から読み込む。
  2. WebSocketを開きます。最初のステートフレームで、 セッションプロファイル そして設定する configure.preset: arm_front_centered. 球体(半径 0.08 m)の内部で最初のランダムなターゲットを生成する(リジェクションサンプリング)。
  3. 1ティックごとに、 set_cursor_position 現在のターゲットに対してコマンドを実行します。カーソルは滑らかに追従します。サービスはレート制限を行い、補間処理を行います。
  4. ユーザーが入力すると n + ENTER キーを押すと、入力スレッドが新しいランダムなターゲットを生成します。 + / - 速度を調整する; q 終了する。

Python(ホールド・トゥ・ムーブ・モデル)

  1. WebSocketを開きます。最初のステートフレームで、以下を確認します status.calibrated — デバイスがまだキャリブレーションされていない場合は、ユーザーに確認を求める。
  2. 読む config.type ワークスペースの半径を選択するには(minverse = 0.04 m、それ以外 = 0.10 m)。
  3. を登録する セッションプロファイル そして設定する configure.preset: arm_front_centered.
  4. 各ティックごとに:キーボードの状態を取得する (W/A/S/D/Q/E)、目標位置を次のように更新する SPEED 各押し付け軸に沿って、作業領域の球体に固定し、送信する set_cursor_position. R ターゲットを原点にリセットします。

パラメータ

名称デフォルト (C++)デフォルト (Python)目的
workspace_radius / RADIUS_INVERSE30.08 m0.10 m (Inverse3) / 0.04 m (Minverse)標的球の半径
speed_step / SPEED0.01 / プレス0.00005 m / ティック1回のやり取りあたりのステップ数
PRINT_EVERY_MS100テレメトリスロットル(Python)
セッションのプロファイルco.haply.inverse.tutorials:position-control同じHaply での特定
キャリブレーションチェック(Python)

Pythonのバリアントチェック status.calibrated 最初の状態フレームから開始し、デバイスがキャリブレーションされていない場合はユーザーに確認を求めます。C++版では、キャリブレーションがすでに完了していることを前提としています。

状態フィールドを読み取る

  • data.inverse3[0].device_id — コマンドを作成するために
  • data.inverse3[0].state.cursor_position — テレメトリ
  • (Python、最初のフレームのみ) data.inverse3[0].config.type —Inverse3 Minverse を選択
  • (Python、最初のフレームのみ) data.inverse3[0].status.calibrated — falseの場合、ユーザーに確認を求める

送信/受信

コミュニケーションのワークフロー

  • C++ バックグラウンドで標準入力スレッドを実行し、そこに書き込みを行う std::atomic<float> ターゲット;WebSocketスレッドは、各ティックごとにそれらを読み取ります。 n + ENTER キーを押すと、入力スレッドが新しいランダムなターゲットを生成します;on q、両方のスレッドが終了しました。
  • Python これはシングルスレッドの非同期処理であり、WebSocketループは各ティックでキーボードの状態をポーリングし、更新を行います position 直接。

Inverse-APIのペイロードは同じです。最初のティックにはセッションプロファイルが含まれ、 configure.preset、それ以降のティックには set_cursor_position.

単一の非同期ループ。キーボードのポーリング(handle_keys) は、スレッドを使用せずに、各ティックごとにインラインで実行されます。 config.type そして status.calibrated 最初の状態フレームから一度読み込まれる。

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"]
radius = get_workspace_radius(data["inverse3"][0].get("config", {}))
# Handshake: profile + preset (one-shot)
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": device_id,
"configure": {"preset": {"preset": "arm_front_centered"}},
}],
}
else:
# Per tick: update position from keyboard (classic polling, not shown), send command
position = handle_keys(position, radius)
request_msg = {
"inverse3": [{
"device_id": device_id,
"commands": {"set_cursor_position": {"position": position}},
}],
}

await websocket.send(json.dumps(request_msg))

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

関連: 制御コマンド (set_cursor_position)マウントとワークスペース(プリセット)型 (vec3)チュートリアル 06(統合版)