Upgrade to Pro — share decks privately, control downloads, hide ads and more …

軽率にWebARアプリでImmersalによるVPSを実装する / localization using immersal in a webar application

軽率にWebARアプリでImmersalによるVPSを実装する / localization using immersal in a webar application

VPS座談会でのLT資料です

にー兄さん

August 20, 2022
Tweet

More Decks by にー兄さん

Other Decks in Technology

Transcript

  1. 軽率にWebARアプリでImmersal
    によるVPSを実装する
    にー兄さん(@ninisan_drumath)
    VPS開発座談会

    View Slide

  2. 発表資料は公開します
    内容はすべてSNS共有OK!

    View Slide

  3. にー兄さん(@ninisan_drumath)
    - 筑波大学 情報科学類
    - HoloLab inc.アルバイト
    - Microsoft学生アンバサダー
    - Iwaken Lab.
    Unity・WebAR・VPSが興味領域
    Project TSUin-MI:
    「つくば市をARネイティブな街にする」が目標
    愛猫→

    View Slide

  4. アジェンダ
    1. 開発したもの
    2. 実現プロセス
    3. おわりに

    View Slide

  5. 開発したもの

    View Slide

  6. WebAR×Immersalの試行
    WebブラウザからWebARアプリを起動して
    Immersalによる位置合わせを実行
    サーバーサイド位置合わせによって実現
    WebARはBabylon.jsというライブラリで実装
    GitHubで公開してます
    https://github.com/drumath2237/immersal-babylon-webxr

    View Slide

  7. 経緯やモチベーション
    (2021年HoloLens Edge上での動作を確認)
    2021年10月頃に調査を開始
    色々進展があったが最後まで実装しきれず中断
    2022/7/1にImmersalのdiscordでひっそりアナウンス
    The WebAR mode has now been fixed on the Dev Portal. Works on
    Android Chrome, and you should have the
    chrome://flags/#webxr-incubations set to 'enabled'. Sample code:
    view page source for view.html
    再チャレンジするか......→できた

    View Slide

  8. 開発環境
    - Immersal REST API(v1.16.1)
    - Babylon.js 5.x
    - Vite
    - TypeScript
    - Chrome for Android (Google Pixel 4a 5G)

    View Slide

  9. 位置合わせをする手順
    1. カメラ画像などの情報を取得
    2. REST APIの仕様に沿ってデータ変換
    3. REST APIへのリクエスト
    4. レスポンスに沿って座標変換

    View Slide

  10. 情報を取得する

    View Slide

  11. 位置合わせに必要な情報
    Immersal REST API(後述)
    のLocalize Imageで必要な情報
    ● カメラ画像
    ● カメラ内部パラメータ
    ● Immersal開発者トークン
    ● マップID配列
    https://immersal.gitbook.io/sdk/api-documentation/rest-api#localize-image-1

    View Slide

  12. 位置合わせに必要な情報
    Immersal REST API(後述)
    のLocalize Imageで必要な情報
    ● カメラ画像
    ● カメラ内部パラメータ
    ● Immersal開発者トークン
    ● マップID配列
    ブラウザ上で取得するのが難しかった
    (セキュリティ上の問題)

    View Slide

  13. Raw Camera Access
    WebXR Device APIに含まれる機能の一つ
    カメラ画像の取得が可能
    現在実験的機能なので、
    ARCoreが対応したデバイスの
    Chrome for Androidでしか動作しない
    加えてWebXR Incubationが有効である必要が
    ある
    詳しくはZennにまとめました
    https://zenn.dev/drumath2237/articles/52d62638c7d06f

    View Slide

  14. 画像データと内部パラメータの取得
    カメラ画像の取得は
    そのままAPIが利用できる
    WebGLTextureとして取得できる
    内部パラメータは右のような計算式で
    取得
    let viewerPose = xrFrame.getViewerPose(xrRefSpace);
    for (const view of viewerPose.views) {
    if (view.camera) {
    const cameraTexture =
    binding.getCameraImage(view.camera);
    }
    }
    function getCameraIntrinsics(projectionMatrix, viewport) {
    const p = projectionMatrix;
    let u0 = (1 - p[8]) * viewport.width / 2 + viewport.x;
    let v0 = (1 - p[9]) * viewport.height / 2 + viewport.y;
    let ax = viewport.width / 2 * p[0];
    let ay = viewport.height / 2 * p[5];
    let gamma = viewport.width / 2 * p[4];
    }

    View Slide

  15. 画像データの変換

    View Slide

  16. 現状整理
    Raw Camera Accessで
    取得できる画像はWebGLTexture
    REST APIへのリクエストには
    Base64エンコードされたPNG画像が欲しい

    View Slide

  17. 逆算して考える
    Base64エンコードされたPNG画像にはPNG画像が必要
    PNG画像を生成するにはピクセル情報が必要
    ピクセル情報を取得るするにはWebGLでなんとかしなきゃ(雑

    View Slide

  18. Immersal本家の実装
    1. three.jsのエンジンからWebGLコンテキストを取得
    2. WebGLコンテキストにWebGLTextureとFrameBufferをバインド
    3. FrameBufferにテクスチャを紐づける
    4. この状態でreadPixels
    5. RGBA値が格納されたUint8Arrayを取得
    6. WebWorker上でpngエンコード(UPNGというライブラリを使用)

    View Slide

  19. 自分の実装
    WebGL APIにぎょっとしたので別の方法で試す
    1. Babylon.jsのRawTextureを生成
    2. RawTextureのフィールドに(強引に)WebGLTextureを代入
    3. RawTexture.readPixelでUint8ClampedArrayを生成
    4. ImageDataへ変換
    5. canvasへ描画してPNG・Base64エンコード
    本家のほうがスマートかも

    View Slide

  20. REST APIへのリクエスト

    View Slide

  21. API仕様に基づいてリクエストするだけ
    ドキュメントを見ながら必要情報を揃える
    エンドポイントへPOST
    https://api.immersal.com/localizeb64

    View Slide

  22. レスポンス
    - マップID
    - 位置
    - 回転行列
    が返ってくる
    リクエストが不適切な場合はerrorだけ
    適切なリクエストだけど位置合わせに失敗したら
    successがfalse
    ゼロベクトルと単位行列が返ってくる

    View Slide

  23. 無事リクエストが通った

    View Slide

  24. 座標変換

    View Slide

  25. 2種類の座標変換
    - Immersal座標系 to Babylon.jsの座標系
    - マップ座標系 to ワールド座標系

    View Slide

  26. ImmersalとBabylon.js
    Immersal Babylon.js
    https://immersal.gitbook.io/sdk/tutorials/how-to-map/custom-im
    ages#rotation
    v1.14→v1.15の間で破壊的変更

    View Slide

  27. マップ座標 to ワールド座標
    Immersal
    マップ座標系の
    カメラの姿勢
    カメラ座標系の
    マップの姿勢
    ワールド座標系の
    マップの姿勢
    レスポンスから変換行列を作成
    逆変換を計算
    リクエスト時のカメラの姿勢を適用
    Map
    Physical
    World

    View Slide

  28. 座標系変換の手動テストツール

    View Slide

  29. 座標系変換の手動テストツール
    スマホを使わずにテストできるツール
    レスポンスデータをとっておく
    姿勢行列の変換処理を実装して
    その挙動をビジュアルで確認
    Babylon.jsのDebugLayerで
    実際の数値も確認
    トライアンドエラーの敷居を
    下げる工夫

    View Slide

  30. 位置合わせができた

    View Slide

  31. おわりに

    View Slide

  32. 展望・まとめ
    - WebARでImmersal位置合わせができた
    - もっといろいろ実験したい
    - WebARでPlaybackできる機能
    - 他のVPSでの検証(PretiaとかGeospatial APIとか)
    - 一般的な環境でも動作してほしい
    - WebXR Device API以外のWebAR VPSに劣る点

    View Slide

  33. 参考文献
    Raw Camera Accessのexplaner
    https://github.com/immersive-web/raw-camera-access/blob/main/explainer.md
    Raw Camera Accessについての記事
    https://zenn.dev/drumath2237/articles/52d62638c7d06f
    Immersal座標系に関するドキュメント
    https://immersal.gitbook.io/sdk/tutorials/how-to-map/custom-images
    デモプロジェクト
    https://github.com/drumath2237/immersal-babylon-webxr

    View Slide