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

07. ベース&マウント 演習場

インタラクティブな方法でデバイスを駆動する マウント変換,そして実演し configure.basis、configure.preset と configure.mount 通信メッセージレベルでの連携方法。一貫した基準を維持し、対話の対象を常に「configure」コマンドに集中させる。

学習内容:

  • 設定 basis 軸の置換("XZY" → Y軸方向の座標系)
  • 選択 プリセット(arm_front),そしてそれがどのような設定を行うかを理解する
  • 実行時に(キーボード操作による)四元数の回転を通じてマウントを上書きする
  • 排他ルール:mount と preset 同じ場所に同時に存在することはできない デバイスの設定 ブロック内
  • 使い捨て configure 意味:キーが押されるたびに、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. ユーザーが「mount」の回転キーを押すと、 pending_configure = true 位置。
  4. 次のティックで:1つを構築する configure.mount ブロック、その変換された rotation 単位四元数(現在のピッチ角/ヨー角に基づき、Z軸、X軸の順に合成)。省略 preset——両者は通信プロトコルにおいて互いに排他的である。
  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 排他

サービスは、その両方を同時に含むものを拒否します。 デバイスの設定 ブロック。ユーザーが mount を上書きすると、このチュートリアルではその後の configure 処理のたびにこの手順が省略されます。 preset。押す R その後、次回の configure 実行時に再び有効になります preset そして削除する mount。

さまざまな入力モード

C++ のバリアントは、バックグラウンドの stdin スレッドで行単位で入力を読み取ります(各文字の後に ENTER キーを押す必要があります)。一方、Python ではメインの非同期ループ内で keyboard キー入力をリアルタイムでポーリングするため、ENTERキーを押す必要はありません。キーが同じであれば、コマンドも同じです。

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

出典: data.inverse3[i].state:

  • cursor_position.y — vec3,地中への貫入深度を算出するために用いる
  • 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))
SDK インストーラーに同梱されています

チュートリアル 07 も SDK とともにローカルにインストールされています。サービスのインストールディレクトリ内をご確認ください。 tutorials/07-haply-inverse-basis-and-mount/。

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

関連情報: Basis 軸の置換 ・ マウントとワークスペース ・ 設備構成 ・ 制御コマンド(set_cursor_force) ・ タイプ(transform) ・ チュートリアル 04(Hello Floor)