メインコンテンツへ移動

05. 位置制御

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

このコースで学べる内容:

  • 利用 set_cursor_position 位置制御モードの場合
  • 同じ基礎となる注文に対する2つの異なる相互作用モデル
  • ターゲットを作業空間内の球体に限定する —Minverse では、これよりも小さい半径が使用されています。Inverse3
  • ワークスペースのプリセットを設定し、原点をワークスペースの中心に配置する

ワークフロー​

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

  1. バックグラウンドで、行単位でバッファに格納されたキー入力を読み取るスレッドを起動します(n, +, -, q), 標準入力(stdin)から。
  2. WebSocket を開きます。最初のステータスフレームで、 セッションプロファイル そして、以下のように設定してください configure.preset: arm_front_centered. 球体内部で最初のランダムなターゲットを生成します(排除法によるサンプリング、半径 0.08 m)。
  3. 各サイクルごとに、コマンドを送信してください set_cursor_position 現在のターゲットに対して。カーソルはターゲットに滑らかに追従します。このサービスはデータ転送速度を制限し、位置を補間します。
  4. ユーザーが入力すると n 次にENTRÉEを押すと、入力ストリームが新しいランダムなターゲットを生成します。 + / - 速度を調整してください; q 終了。

Python(移動モデル維持)​

  1. WebSocket を開きます。最初のステータスフレームで、以下を確認してください。 status.calibrated — デバイスがまだキャリブレーションされていない場合は、ユーザーにメッセージを表示してください。
  2. Lisez 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 / サイクル相互作用によるものではない
PRINT_EVERY_MS—100テレメトリの制限(Python)
セッションプロファイルco.haply.inverse.tutorials:position-control同一のHaply Hub での認証を可能にします
キャリブレーションの検証(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 — 値が偽の場合、ユーザーにプロンプトを表示する

送信と受信​

発表の進行​

  • C++ 標準入力を読み取り、ターゲットへ書き込むバックグラウンドスレッドを実行する std::atomic<float> ; WebSocketスレッドは、各サイクルごとにそれらを読み取ります。on n 次にENTRÉEを押すと、入力ストリームが新しいランダムなターゲットを生成します。 q、二人の息子は立ち止まった。
  • Python 非同期かつシングルスレッドです。WebSocketループは各サイクルでキーボードの状態を照会し、更新を行います。 position 直接。

Inverse-APIのペイロードは同じです。最初のサイクルではセッションプロファイルが転送され、 configure.preset、そしてそれ以降のサイクルでは、以下のもののみを輸送する set_cursor_position.

一意な非同期ループ。キーボードのポーリング(handle_keys) は、実行スレッドを使用せずに、ループの各サイクルで直接実行されます。 config.type et 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))
SDKインストーラーに含まれています

チュートリアル 05 も SDK とともにローカルにインストールされています。詳しくは tutorials/05-haply-inverse-position-control/ サービスのインストールディレクトリ内。

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

関連項目: 制御コマンド (set_cursor_position) ・ モンタージュと作業スペース(プリセット) ・ 型 (vec3) ・ チュートリアル 06(複合)