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

07. ベース&マウント・プレイグラウンド

デバイスの機能をインタラクティブに制御します マウント変換 そして、その方法を示しています configure.basis, configure.presetそして configure.mount ワイヤ上で共同作業を行います。水平方向の画面レイアウトが固定されるため、操作の焦点は「configure」コマンドに集中したままになります。

学習内容:

  • 設定 基底置換 ("XZY" → Y-upアプリケーションフレーム)
  • 選ぶ プリセット (arm_front) およびそれが何を設定しているかを理解する
  • 実行時に回転クォータニオンを使用してマウントを上書きする(キーボード操作)
  • 排他性ルール: mount そして preset 同じ場所には共存できない デバイスの設定 ブロック
  • 単発 configure セマンティクス:キーが押されるたびに、正確に1つの設定メッセージが送信される
  • (C++ Glaze) 排他的なフィールドのモデル化 std::optional

ワークフロー

  1. 最初のメッセージで: セッションプロファイル, configure.basis: "XZY"そして configure.preset: arm_front送信を開始 set_cursor_force 固定床用。
  2. 各ティックごとに:カーソルのY座標を読み取り、計算する force_y = max(0, (floor_pos - y) * stiffness)、送信してください。
  3. ユーザーがマウント回転キーを押すと、フラグ pending_configure = true.
  4. 次のティックで: configure.mount 変換が適用されたブロックで rotation は単位クォータニオン(現在のピッチ/ヨーをZ→X順に合成したもの)です。省略 preset — これら2つは、回線上で互いに排他的である。
  5. リセットキー (R) オーバーライドを解除します。次に configure を実行すると、デフォルト設定に戻ります。 preset また。

パラメータ

名称デフォルト目的
BASIS"XZY"軸の回転— Y軸上向きの適用フレーム
DEVICE_PRESET / DEVICE_CONFIG_PRESET"arm_front"名前付きプリセット— 原点はデバイスの基部
FLOOR_POS_Y0.0 m固定床面(アプリケーションY)
STIFFNESS1000 単位なし床のばね定数
MOUNT_STEP_DEG10°キーを押すごとに回転
PRINT_EVERY_MS200テレメトリースロットル

操作方法

キーアクション
W / Sデバイス軸 +X を中心にマウントを±10°回転させる(ピッチ)
A / Dデバイス軸 +Z を中心にマウントを±10°回転させる(ヨー)
Rマウントをリセット — プリセットに戻す
Hコントロールを表示
Q終了
mount そして preset 互いに排他的である

このサービスは デバイスの設定 両方を含むブロック。ユーザーがマウントを上書きすると、チュートリアルでは preset 以降のすべての configure 実行において。を押すと R 再度有効にする preset 次回の設定と削除について mount.

さまざまな入力モデル

C++のバリアントは、バックグラウンドのstdinスレッドで1行ごとの入力を読み込みます(各文字の入力後にEnterキーを押してください)。Pythonは keyboard メインの非同期ループ内でリアルタイムにキー入力をポーリングするパッケージ — ENTERキーを押す必要はありません。対応するキーとコマンドは従来と同じです。

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

差出人 data.inverse3[i].state:

  • cursor_position.yvec3、床への貫通を計算するために使用される
  • current_cursor_force — テレメトリ用に報告された

送信/受信

ペイロードの形状は各バリエーションで共通ですが、興味深い違いは、それぞれが互いに排他的な mount / preset 分岐処理と、入力スレッドがWebSocketスレッドにシグナルを送信する方法。

単一の非同期ループと、 keyboard パッケージ。 pending_configure は、キーハンドラによって設定され、 configure ブロックが送信されます。

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"]
# Handshake: profile + basis + preset
request_msg = {
"session": {"configure": {"profile": {"name": SLUG}}},
"inverse3": [{
"device_id": device_id,
"configure": build_configure_block(first_handshake=True),
# -> {"basis": {"permutation": "XZY"},
# "preset": {"preset": "arm_front"}}
}],
}
else:
handle_key_inputs() # may set pending_configure = True (classic, not shown)

y = data["inverse3"][0]["state"]["cursor_position"]["y"]
force_y = 0.0 if y > FLOOR_POS_Y else (FLOOR_POS_Y - y) * STIFFNESS

entry = {
"device_id": device_id,
"commands": {"set_cursor_force":
{"vector": {"x": 0.0, "y": force_y, "z": 0.0}}},
}
if pending_configure:
entry["configure"] = build_configure_block(first_handshake=False)
# -> {"mount": {...}} OR {"preset": {...}} (never both)
pending_configure = False

request_msg = {"inverse3": [entry]}

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

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

関連: 基底の置換マウントとワークスペースデバイスの設定制御コマンド (set_cursor_force)型(変換)チュートリアル 04(Hello Floor)