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

09. WebSocket ワークスペースナビゲーター

デバイスの ワークスペースの位置をリアルタイムで表示 ストリーミングで set_transform WebSocketチャネル経由のコマンド。このチュートリアルでは、HTTPを使用してセッションとデバイスを検出します(まさに チュートリアル 08)、その後、WebSocketを開いて、各ティックごとに位置情報の更新を送信します。

これは、2つの変換操作の違いを示しています:

操作チュートリアル一般的な使い方
configure.mount — 永続的なマウント変換08デバイスの物理的な取り付け方法を記述するために、一度(またはごくまれに)設定します
set_transform — ワークスペースの永続的な変換09(今回)これも永続的ですが、ワークスペースをリアルタイムで移動するために、毎ティックストリーミング可能です

どちらのコマンドも、 HTTP と WebSocket、そしてどちらも 持続的な — このサービスは、最後に送信した値を記憶しています。違いは、その目的と更新頻度にあります: configure.mount は更新頻度の低い(物理的な設定)用途向けに最適化されていますが、 set_transform 高頻度でのストリーミング(シーン移動)に最適化されています。

使用 set_transform ワークスペースの原点が、実行時に変化する要素を追跡する必要がある場合――例えば、手の動きを追跡したり、手続き型オフセットをアニメーション化したり、オペレーターが仮想ワークスペースをリアルタイムで微調整できるようにしたりする場合などです。

マウントとワークスペースが親子関係にある

個別に、 configure.mount そして set_transform 一見同じ効果をもたらすように見えるが、実際には 親が育てた: ワークスペース変換が適用されます さらに 座標パイプライン内のマウント(device → basis → mount → workspace → application). 参照 マウントとワークスペース パイプライン全体については。

ユースケース

  • ワークスペースのリアルタイム移動。ハプティックシーンを停止させることなく、デバイスのカーソルワークスペース(エンドエフェクタが到達可能な範囲)を移動させます。
  • オペレーター主導の位置合わせ。メインのハプティックアプリが実行されている間、別の端末の担当者が矢印キーを押してワークスペースを移動させます。ライブセッション中のユーザーごとのデスクキャリブレーションに便利です。
  • ワークスペースの動的な移動。スクリプト(オーディオ反応型、物理演算駆動型など)からワークスペースの位置を制御し、各ティックごとに位置のみのトランスフォームパッチを送信します。

前提条件

チュートリアル09では、アクティブなWebSocketセッションが必要です。つまり、Inverse3 実行中のInverse3 クライアントが必要です。チュートリアル09では、そのセッションに接続し、ワークスペースをリアルタイムで切り替えます。

セッションを立ち上げる最も手っ取り早い方法

Haply を開き、Orbのデモを起動してください。これにより、すぐに操作を開始できる常時接続のハプティックセッションが開きます:

./09-haply-inverse-ws-remote-control --session co.haply.hub::demo-orb
python 09-haply-inverse-ws-remote-control.py --session "co.haply.hub::demo-orb"

「Orb」シーンでは、ワークスペースの原点に球体が描画されます。チュートリアル09の手順に従ってワークスペースを移動させると、シーン全体がリアルタイムで移動し、即座に視覚的なフィードバックが得られます。

ハプティック・ループを実行する他のチュートリアル(01~07)でも同様に動作します。まず1つのターミナルでそれを実行し、次に別のターミナルでチュートリアル09を起動して、対話モードでセッションを検出させます。

使用方法

# Discover session interactively, use first detected device
./09-haply-inverse-ws-remote-control
python 09-haply-inverse-ws-remote-control.py

# Target the Haply Hub Orb demo directly
./09-haply-inverse-ws-remote-control --session co.haply.hub::demo-orb
python 09-haply-inverse-ws-remote-control.py --session "co.haply.hub::demo-orb"

# Target a session directly, specify device
./09-haply-inverse-ws-remote-control --session :my_profile:0 --device A14
python 09-haply-inverse-ws-remote-control.py --session "#42" --device A14

操作方法

キーを押し続けると連続して移動します。離すと停止します。

キーアクション
/ +X / −X
/ +Y / −Y
Page Up / Page Down+Z / −Z
= / -ナビゲーションの速度を上げる/下げる
0ワークスペースを原点にリセットする
Hヘルプを表示
Esc終了 (Ctrl+C (これも有効です)

仕組み

ステップ 1 — HTTP セッションとデバイスの検出

このチュートリアルでは、同じものを再利用しています discover_session() / discover_device() ヘルパーとして チュートリアル 08: GET /sessions (または GET /sessions/<selector>--session)、それなら GET /devices (または --device (直接)。どちらのヘルパーも、同じCLIフラグを受け付け、その動作は全く同じです。 SESSION_HELP text — チュートリアル00または08のセレクタを、そのままここで使用できます。

ステップ 2 — WebSocket セッション、初回メッセージのハンドシェイク

このチュートリアルでは、WebSocketを開いて ws://localhost:10001. について 最初のメッセージのみ, セッションプロファイルの登録を送信します:

{
"session": {"configure": {"profile": {"name": "co.haply.inverse.tutorials:ws-remote-control"}}},
"inverse3": [{"device_id": "...", "commands": {"set_transform": {"transform": {"position": {"x": 0, "y": 0, "z": 0}}}}}]
}

以降のティックは省略 session — ただ inverse3 コマンド配列が送信されます。

ステップ3 — ティックごと set_transform

set_transform ~を受け入れる 部分変換 — 変更したいフィールドのみ。このチュートリアルでは位置のみを送信します。回転と拡大縮小はセッションのデフォルト値( configure.mount(もしあれば)。

{
"inverse3": [{"device_id": "...", "commands": {"set_transform": {"transform": {"position": {"x": 0.02, "y": 0.0, "z": 0.01}}}}}]
}

位置情報はティックごとに蓄積されます。約1 kHzで、サービスは再適用を行います set_transform 各ティックごとに(ゼロオーダー・ホールド)、ワークスペースは最後にプッシュした位置に保持されます。

set_transformconfigure.mount

どちらのコマンドもセッションごとに永続的な変換を保存しますが、ワークスペースの変換は さらに パイプライン内のマウント(参照: マウントとワークスペース). チュートリアル09の配信中 set_transform 各ティックごとに、新しいWebSocketフレームが以前にストリーミングされたワークスペース変換を上書きします。そのため、他のクライアントがストリーミングしている set_transform 同じデバイスへの設定は、次のティックで上書きされます。 configure.mount は独立しており、その値を維持します。実際には、関心事ごとに1つのチャネルを選択してください。物理的な設定にはmountを、 set_transform ライブナビゲーション用。

スレッドモデル(C++)

このC++チュートリアルでは、位置の累積値を共有する2つのスレッドを使用しています:

スレッド役割
メインスレッド閲覧数 std::getline(std::cin, ...)、トークンを解析し、更新する nav_vel[] そして default_step
WebSocket コールバックスレッド進歩 nav_pos[] を使用して nav_vel[] * dt、シリアライズする set_transform、送信します

std::mutex nav_mutex 保護する nav_pos[], nav_vel[]そして default_step. その last_tick タイムスタンプと first_ws_msg flag は WS コールバックのローカル変数であり、ミューテックスは不要です。

ws.onmessage = [&](const std::string &) {
float pos_snap[3];
{
std::lock_guard<std::mutex> lk(nav_mutex);
for (int i = 0; i < 3; ++i) nav_pos[i] += nav_vel[i] * 0.001f; // mm/frame → m
for (int i = 0; i < 3; ++i) pos_snap[i] = nav_pos[i];
}
// build and send set_transform with pos_snap
};

出典

SDKインストーラーに同梱

チュートリアル 09 は SDK とともにローカルにインストールされています。次の場所を確認してください tutorials/09-haply-inverse-ws-remote-control/ サービスのインストールディレクトリの下に。

関連: set_transform コマンドセッション — 初回メッセージのハンドシェイクマウントとワークスペースセレクタチュートリアル 08 — HTTP リモート設定チュートリアル 07 — ベースとマウント