Haply Inverse SDK 3.5.0 {#haply-inverse-sdk-350}
1年前の API 刷新以来、最大規模のリリースです。3.5.0 では、統合された 3D 数学レイヤー、Minverse の完全サポート、型付きイベントストリーム、完全な設定 API、そしてより整理された HTTP インターフェースを導入します。あわせて、1年分のバグ修正と使い勝手の改善も含みます。
ハイライト {#highlights}
統合された 3D 数学レイヤー — デバイスの基底(フレーム)、マウント変換、ワークスペース変換、ナビゲーション変換のためのファーストクラスのプリミティブを備えた、組み合わせ可能な変換パイプラインです。さらに、ローカル、セッション、アプリケーション、内部の各空間の間で、明示的な変換が可能です。Bubble Navigation — 形状を持つゾーン(SDF プリミティブ)を通じて、大規模な仮想ワークスペース内を移動できます。速度マッピングによるレート制御、ヒステリシスを考慮した衝突検出、そして必要に応じてカーソル方向へのドリフトに対応します。HTTP と WebSocket から完全に設定でき、アプリ空間でのラウンドトリップにも対応しています。型付きイベントストリーム — デバイスのライフサイクル、安全アラート、キャリブレーション、バッテリー、制御レートの警告、非推奨のヒントのための専用の WebSocket イベントチャネルです。Settings API — HTTP による CRUD、型ヒント、範囲制約、説明を備えた、完全なキーと値の設定システムです。従来のネストされた設定ファイルを置き換えます。デバイス設定の統一 — すべてのデバイスで共通の HTTP ルートを1セット用意しています: basis、mount、preset、transform、filters、handedness、torque_scaling、gravity_compensation、home_return。Minverse とペンの同期キャリブレーション — デバイスとそのペンが一緒にキャリブレーションされるようになりました。グリップが物理的に取り付けられるまで、キャリブレーションはロックされたままです。HTTP の使い勝手の向上 — インデックスベースのデバイスセレクター(ID が不要で、インデックスでデバイスを指定可能)、WebSocket と共通のリクエスト/レスポンス形式、オプトインの {ok, error, data} エンベロープ(?format=json)、そしてワイルドカードによるセッションセレクターを提供します。新機能 {#new-features}
デバイス {#devices}
Minverse — 本リリースで正式サポートを提供します。検出、準備完了シーケンス、安全通知、同期キャリブレーションのワークフローが含まれます。Ruko と Kingfisher を、正式なグリップ製品タイプとして認識するようになりました。デバイスシミュレーターのサポート — 実機と並行して、ソフトウェアでシミュレートされたデバイスを検出し、通信できます。接続ループの保護 — 不正な動作をするポートは自動的にブロックされます。POST /ports/{port}/reset でリセットできます。ペン取り付けのハートビート — デバウンス処理により、グリップの取り付け/取り外しを確実に検出します。セッション、コマンド、WebSocket {#sessions-commands-websocket}
セッションプロファイルのフィルタリングと永続化 — セッションはプロファイル名と必要な SDK バージョンを宣言でき、サービスは再接続をまたいでこれらを記憶します。クライアントや監視ツールは、このプロファイルでセッションをフィルタリングし、対象を指定できます。セッションごとのコマンドバッファ — 処理の遅いセッションが、ほかのセッションを停止させることがなくなりました。単発コマンド用の明示的な `configure` マップ — デバイスごとの basis、preset、mount、force_gate、damping、およびセッションごとの profile と basis が、すべて configure に含まれるようになりました。出力の設定マップと揃えてあるため、送信した内容が、読み取った内容とラウンドトリップで一致します。カスタマイズ可能なデバイスマウント — 組み込みのワークスペースプリセット(defaults、arm_front、arm_front_centered、led_front、led_front_centered)から選択するか、明示的な変換を送信できます。マウントを手動で変更すると、プリセットは自動的に custom に切り替わります。名前付きコマンドフィールド — 汎用の values 配列の代わりに、position、vector、angles、torques を使用します。set_angular_torques が set_angular_torque を置き換えます(単数形は非推奨です)。セッションフレームの拡張 — v3.0 および v3.1 のセッションフレームに、拡張可能な config、state、status オブジェクトが含まれるようになりました。新しい出力フィールドには、current_cursor_force、current_cursor_position、current_angular_torques、current_angular_position、control_domain、control_mode、transform、transform_velocity、より詳細な config.*、そして status.safety(デフォルトでは非表示)があります。変換の部分更新 — マウント、ワークスペース変換、ナビゲーションシェイプで、変更したいサブフィールド(position、rotation、scale)だけを送信できます。HTTP {#http}
GET / — サービスのバージョン。GET/POST/DELETE /settings および /settings/* — キーと値の完全な設定 API です。GET /sessions/{session} および GET/POST/DELETE /sessions/{session}/profile。GET /devices?session=<selector> — デバイスの座標を、指定したセッションのアプリケーション空間に変換します。インデックスベースのデバイスセレクター — ID を知らなくても、インデックスで任意のデバイスを指定できます(最初の Inverse3 には /inverse3/0/...、Inverse ファミリーのすべてのデバイスには /inverse__ITALIC_italic-1__/...)。リクエスト/レスポンス形式の統一 — POST/GET のボディは、WebSocket と同じ command_data JSON 形式を使用します。一方のトランスポート向けに書かれたコードは、もう一方でも動作します。オプトインのエンベロープ — 任意のルートに ?format=json を指定して有効化します。/settings* と GET /home_return は、デフォルトで {ok, error, data} になります。生の形式を使う場合は ?format=plain を指定します。セッションセレクターのワイルドカード — プロファイル名では、*(任意の文字列)と ?(任意の 1 文字)を使用できます。パーセントデコードされたセレクター — %2A、%3A などは、ルーティングの前にデコードされます。イベント {#events}
communication/events/port 上の専用 WebSocket イベントストリーム。デバイスのライフサイクル、安全機能(非常ブレーキ、異物検出、ストール)、キャリブレーションの失敗、バッテリーアラート、セッションの警告、制御レートの低下および重大な低下、入力の検証、非推奨のヒントを含む、24 種類の型付きイベントカテゴリ。オブザーバビリティ {#observability}
プロファイリング時、ログメッセージはレベルに応じた色で Tracy に転送されます。すべての HTTP ハンドラーに Tracy ゾーンを設定しています。メインループのタイミング統計イベント。ログディレクトリとサーバーのホスト名を設定可能(Docker に対応)。3.6 で提供予定の機能 {#coming-in-36}
SDF ハプティックエフェクト(SDF HFX) — 基盤は 3.5 に含まれています(モジュール、ライフサイクル、モジュールが提供するコマンドおよび状態のシリアライズ)。公開 API は、完全なドキュメントとともに 3.6 で提供される予定です。改善点 {#improvements}
力の振動フィルター — 軸ごとの振動検出、8 段階の段階的な回復、ヒステリシス付きの進入投票、非対称な解除ウィンドウを備えています。ランタイムのフォースゲートフィルター — WebSocket または HTTP 経由で configure.force_gate.gain を使って設定できます。永続的なデフォルト値も設定できます。メインループの最大周波数を 32 kHz に引き上げ — 高精度なアプリケーション向けです。WebSocket ペイロードの縮小 — 恒等値がデフォルトの変換サブフィールド(position = 0、rotation = identity、scale = 1)は、デフォルトで出力から省略されるようになりました。これによりペイロードサイズが小さくなり、古い Unity パッケージの 4 KB メッセージ上限との互換性も回復します。すべてのフィールドを出力に含めたいコンシューマー向けに、2 つの詳細設定(serialization/explicit_fields、serialization/force_complete_transforms)が用意されています。メインループのジッター低減 — WebSocket のメッセージ処理は、JSON の解析とネットワーク送信の間もメインループの tick をブロックしなくなりました。セッションの tick スケジューリングは、レスポンスのシリアライズより前に移動しました。サーバーはデフォルトで localhost のみ — ネットワークアクセスは、communication/bind_all_interfaces 設定で明示的に有効化できます。デバイスセレクターのワイルドカードは前方一致構文を使用します(例: inverse* は Inverse ファミリーのすべてのデバイスに一致)。ダンピングコマンド を、force_gate と並べて configure マップに移動しました。ローテーションするファイルロガー に置き換わり、ディレクトリを設定できるようになりました。モジュールが提供するコマンドと状態 — モジュールは、コアスキーマを変更せずに、独自のコマンドを追加したり、フィールドを設定したり、状態出力を WebSocket フレームに組み込んだりできます。修正 {#fixes}
1年分のバグ修正のうち、特に影響の大きいものは以下のとおりです。
セッション速度の不安定化(特定の条件下)。GripHook (Verse Grip Stopper) は、シミュレーションが実行されていない場合に正しく解放されませんでした。Inverse3 のタイムアウトが短すぎたため、起動の遅いデバイスで切断ループが発生していました。Windows でのサービス停止時の不完全な終了 — シャットダウン時に HTTPサーバーが必ずしもクリーンアップされていませんでした。再接続ループ(サービスが古いファームウェアバージョンに未対応のコマンドを送信した場合)。Bluetooth デバイスの列挙により、Bluetooth アダプターを搭載したシステムでログが大量に出力されていました。サービスを連続して再起動した際のクラッシュ。Wireless Verse Grip ドングルのフリーズ(スリープ/復帰後の Ubuntu ノートPCで発生)。Linux および macOS における Wireless Verse Grip のハンドシェイクは、最初の検出試行に失敗した場合に正しくフォールバックするようになりました。MacOS 設定ファイルの場所 — 設定は誤ったパスではなく ~/Library/Application Support/ に保存されるようになりました。Linux および macOS での SIGSEGV シグナル処理 — マルチスレッドのクラッシュキャプチャが有効な場合、致命的なシグナルでプロセスがループしなくなりました。セッション間のコマンド上書き — あるセッションの設定コマンドが、別のセッションのコマンドによって黙って置き換えられることがありましたが、現在は正しくフィルタリングされ、マージされるようになりました。プローブコマンドによる設定の上書き — probe_position を送信する監視セッション(例: Haply Hub)が、保留中の basis / preset / profile の変更を黙って上書きしなくなりました。プロトタイプグリップの表示 — プロトタイプのハードウェアが、カスタムグリップではなく標準グリップとして誤って表示されていました。従来の `set_basis` 行列規約が、未移行のクライアントに対して再び適用されるようになりました。Inverse3 の強制キックが、セッション切断時に残留する力のスパイクを発生させなくなりました。WebSocket の接続喪失レース(急速な接続・切断のサイクル中)。WebSocket の `session_id` が、一部の送信ペイロードで 0 としてシリアライズされていました。Windows では、--dev と組み合わせた場合でも --log-level が尊重されるようになりました(以前は debug に黙ってリセットされていました)。非推奨 {#deprecations}
以下の機能は引き続き動作しますが、将来のメジャーバージョンで削除される予定です。該当する場合、レスポンスには deprecation_warning フィールドが含まれます。
| 非推奨 | 置き換え先 |
|---|---|
| POST /force_scale | POST /settings/devices/inverse*/filters/force_scale/gain |
| POST /gravity_compensation | POST /{device}/{id}/config/gravity_compensation |
| POST /torque_scaling | POST /{device}/{id}/config/torque_scaling |
| POST /device_handedness | POST /{device}/{id}/config/handedness |
| POST /serial_enable | POST /settings/communication/serial/enabled |
| POST /experimental/features/grip_dropped_simulation_stopper | Settings API |
| POST /experimental/features/screensaver_enable | Settings API |
| WebSocket command_data.values | position, vector, angles, torques |
| WebSocket set_angular_torque | set_angular_torques |
| WebSocket probe_cursor_position | probe_position |
| WebSocket set_coordinate_origin | configure.preset |
| WebSocket session-level set_basis | configure.basis |
互換性に関する注意事項 {#compatibility-notes}
3.4.19 からの破壊的変更はありません。既存の連携に関する注意点は 2 つあります:
非推奨の HTTP エンドポイントのレスポンスには、deprecation_warning フィールドが含まれるようになりました。レスポンススキーマを厳密に検証しているクライアントでは、この追加フィールドを許容するよう設定してください。WebSocket の command_data にある values フィールドは非推奨ですが、引き続き解析されます。名前付きフィールドの使用を推奨します。チュートリアルとドキュメント {#tutorials-documentation}
新しいチュートリアル:05 位置制御、06 組み合わせ(Inverse3 + Verse Grip)、07 Basis と Mount、08 HTTP リモートコンフィギュレーター、09 WebSocket リモートコントロール、10 イベントストリームリスナー。新しい Glaze 版:既存の nlohmann/json 版と並んで、すべての C++ チュートリアルに追加されました(cpp-glz/)。すべてのチュートリアルを書き直し、v3.1 API に対応させました(ポート 10001、configure.preset、名前付きのコマンドフィールド、print_state() ヘルパー)。削除 — 古い Verse Grip Stopper チュートリアルは削除され、新しい組み合わせチュートリアルに置き換えられました。公開ドキュメントを更新しました(SDK ガイド、API リファレンス、ハードウェアのページ)。