これちのPost-it

技術ネタをペラペラと

Nreal Developer Gathering に参加してきた

Nreal Developer Gathering@10/8渋谷に参加し、nreal 開発者のプレゼンを聞き実機デモを体験してきました。

ar-japan.connpass.com

個人的に nreal なかなか良かったので MR アプリ開発者目線で感じたことをまとめようかなと。書きなぐりですが。

(Nreal と nreal どっちが正しいか分かりませんが本記事では nreal に統一)

nreal 基本情報

https://www.nreal.ai

www.itmedia.co.jp

ここらへん読めば雰囲気掴めると思いますが、

  • 1199$の Developer Kit 版と499$の Consumer Kit 版がある
    • Dev 版は購入申請可能。Cons 版は 2020年早期より出荷予定
  • 軽い。88g
    • MagicLeap と同様にコンピューティングユニットが外出しされ、グラス部の重さを抑ている
    • Snapdragon845 以上の Android スマートフォンへUSB type-C?経由で接続することも可能
      • PC 接続も可能
  • SLAM, 6DoF, 平面検知, イメージトラッキング等が可能
  • マイクとスピーカーも搭載し将来的には音声コントロールにも対応予定
  • 対角52°の FoV
  • 日本の MR 市場を重視
    • KDDI とパートナーシップを組んでる

nreal 開発者のプレゼンで分かったこと

  • nreal の社員は現在120人
    • 45%は修士
    • 北京に HQ
  • スピーカーは DTS surround 対応
  • 用途は game/sns/education/production と特に制限なく想定
  • preorder 数は 4K で US>JP>CN の順に多い
  • 会社を立ち上げてから2年でリリース
  • 度つきレンズが装着可能(マグネット式)で、眼鏡を外して体験できた
  • 表示素子のマイクロ OLED は片目フル HD の120Hz駆動(ソニー製?
    • ほぼ半球形の曲面レンズorハーフミラーで前方に飛ばした光をレンズ部の曲面ハーフミラーで収束させて表示
  • CES2020 までは Dev 向け開発、CES2020 以降は Cons 向け開発にシフト
  • 大手町に日本支社を立ち上げ
  • 将来のロードマップにはハンドトラッキング
  • Android Native App が nreal で動作するらしい(詳細は不明
  • MESON 社、Psychic VR Lab 社は nreal のエバンジェリスト
    • MESON 社は nreal を使って街空間での AR コミュニケーションを開発、実証実験

nreal の所感

まず良かった点。

  • デザイン良し。軽いので日常使いできそう
    • デザインには相当力を入れているらしい
  • SLAM の安定感は Holo/ML1/ARKit/ARCore に比べると劣りブレが気になる
    • ただかけやすさ、つけ心地、値段等を鑑みると Holo/ML1 より全体として良い感じ
  • 視野角が Holo より広く、ML1 と同等程度の印象
    • ただし横長視野角なのでキャラクターを近くに表示させたり、とかは難しそう
  • Android 端末と接続できるので、GPS を活用したり他アプリと連携したりとコンテンツの幅を広げられそう
  • nreal でデモすれば「 AR グラスを日常的につけられる時代がきたら〜」の説得力が増しそう
  • コントローラー付きなのでインタラクティブなゲームも作れそう
    • ただしコントローラーは 3DoF なので用途は限られるかも

ここからうーんな点。

  • 現実がかなり見えづらい
    • 体感70%ほど外の情報が遮断されていた気がしたので nreal をつけて外を出歩くのは厳しそう
    • 現実がほぼほぼ見えないせいで AR オブジェクトが現実にある感(MR 感)が薄い
  • オクルージョン無いのが残念
  • Spatial Computing してる感が Holo/ML1 に比べて薄い、というか無い
    • イメージとしては SLAM つき Google Glass のような印象で、眼の前にディスプレイがあるなーという感じ(伝わるかな・・
    • 床や壁の上に何か出したり、という感じではなさそう。今まさに環境の認識まわり頑張っているところなのかも?
    • マップの保存等についても言及されてなかったけど、まだ実装されていないのかも?

という感じでした! ちょっとふわっとした感想が多いけど、少しでも nreal をかけた印象が伝われば。

Oculus Quest Mixed Reality Capture Tools セットアップ手順

(注意)現状では Oculus Quest のゲームを Mixed Realty Capture(以降 MRC と略)できないようです。自分で開発した MRC 対応アプリ、もしくは MRC に対応したアプリ(まだ0個)のみ撮影が可能です。

しかも途中で OBS Studio の使い方がわからずギブアップしてます・・すみません。何かわかれば追記していくつもりです。

ただ今後 MRC 対応 Quest アプリが増えてくるかもなので、現状できたところまでですが、公式のセットアップの日本語訳版ということでメモ。

参考リンク

developer.oculus.com

vrinside.jp

下準備

必要な機材

必要なソフトウェア

// フォルダ構成
Oculus_Quest_MRC_Tools_1.0
    |- MRCCameraCalibration_Quest
    |      |- MrcCameraCalibration.apk  // Oculus Quest にインストールする apk
    |- oculus-mrc_OBS
    |      |- data
    |      |- obs-plugin
    |- OVRCameraCalibration_PC  // PC 側で起動するカメラキャリブ用ファイルが入ってる
           |- OVRCameraCalibration.bat
           |- etc

必要な資材

  • Oculus_Quest_MRC_Tools_1.0/OVRCameraCalibration_PC/Assets/pattern.png を印刷
    • カメラのキャリブで使うためサイズや画質は変更しない方がいいとのこと(なので画像はここには貼りません)
    • ただし自分は画像をスマホ上に表示してそれを使いました。これでも問題なさそうです
  • Oculus Quest と Rift S の近接センサー(額の前あたりにあるやつ)を覆うテープ
    • キャリブ中テープを使って HMD の電源が落ちないように

カメラキャリブレーション

  1. Quest を adb コマンドが使える PC に接続
  2. adb install -r MrcCameraCalibration.apk
  3. Quest から MRC Camera Calibration Service を起動して IP アドレス(192.168.1.4)をメモ
  4. カメラを設置(今後カメラ位置は動かないように)
  5. Quest の近接センサーにテープを貼り電源がオフにならないようにする
  6. OVRCameraCalibration.bat 内の IP アドレスを VSCode 等で開き先ほど調べた Quest の IP アドレスに変更
  7. OVRCameraCalibration.bat を起動し Quest で起動しているアプリと接続が開始すると QuestMode というウインドウが開く
    • f:id:korechi:20190705012912p:plain:h200
  8. Calibrate Camera を選択
  9. 適切なカメラを選択し次へ
  10. 画質は 1920*1080 が推奨なのでそれで設定して次へ
  11. Start Intrinsic Calibration を選択
    • この時点でカメラ映像が見えてない場合はどこかで設定を間違えている可能性があります
  12. マーカーを画面上に表示されているボックスに合わせる作業を20回やりカメラの歪みを補正
    • 認識がうまくいくと枠内が虹色になります
    • 最後に出てきた値が1以下なら良いみたい
  13. static camera を選択して次へ
  14. 今度は Oculus Rift S のセンサーにシールを貼り、矩形内に入れて A ボタンを押して進める f:id:korechi:20190706124321p:plain
  15. Oculus Touch コントローラとバーチャル Touch コントローラが重なって表示されていたら成功なので mrc.xml という名前で保存

キャリブレーションファイルを Quest へ転送

Mixed Reality Capture を行いたいアプリへ先ほど作った mrc.xml をコピーします。

以下は例として Beat Saber 1. android file transfer や adb コマンドを使用して mrc.xml/Android/data/com.{yourorgname}.{yourappname}/files/ にコピー + adb なら adb push <path of the saved mrc.xml> /sdcard/Android/data/com.{yourorgname}.{yourappname}/files/ + android file transfer なら↑の場所にドラッグ&ドロップでコピー

OBS を使ってシーンを複合

  1. Oculus_Quest_MRC_Tools_1.0\oculus-mrc_OBS の下にある data, obs-plugins を obs-studio のルートにコピー
    • 例) C:\Program Files\obs-studio
  2. OBS Studio を起動
    • OBS Studio の使い方はここ

ここからは OBS Studio の使い方がよくわからなかったため、公式ドキュメントを読んで進めてください。

とりあえずここまで。中途半端ですみませんがギブアップ・・

Unity で地図が表示可能な mapbox を触ってみた(初級編)

はじめに

XR+位置情報なゲームを作りたいなーと思い Unity 向けにパッケージが公開されてる mapbox を触ってみました。

公式ドキュメントはこちら

docs.mapbox.com

今回は mapbox SDK を使って地図をUnity 上で出してみることを実現したいと思います。こんな感じです。

f:id:korechi:20190521171841p:plain

環境

Maps SDK for Unity v2.0.0

Unity 2019.1.2f1

使い方

Unity でのセットアップ方法は↑に書いてあるため割愛。

基本的には unitypackage をインポートし Mapbox->Prefabs->Map プレハブを hierarchy 上に配置後 Play すれば地図が表示されます。

f:id:korechi:20190521101650p:plain

この Map プレハブについてる Abstract Map(Script) から地図のいろんなパラメータの調整や、レイヤの追加等が可能です。

ただし↑の公式ドキュメントは SDK バージョンが1.4.0対応っぽく少し古いため、一部 API 仕様が微妙に違うので注意。(2019/5/21現在)

Scene の中心に9マスに分割された地図が表示されています。しかしこのままでは画面をドラッグしてカメラ視点を変えたり、緯度経度を自由に指定する等できません。

SDKMapbox->Examples にあるサンプルを参考にいろんな操作ができることを確かめてみてください。

では実際にいろいろ触ってみようと思います。

その前に

Unity 2019 で SDK をインポートしたら下記のエラーをはいたので、

Library/PackageCache/com.unity.xr.arfoundation@1.0.0-preview.22/Runtime/AR/ARSessionOrigin.cs(3,19): error CS0234: The type or namespace name 'SpatialTracking' does not exist in the namespace 'UnityEngine' (are you missing an assembly reference?)

https://github.com/Unity-Technologies/arfoundation-samples/issues/79#issuecomment-450263059

どうもここが参考になりそうとのことで

"com.unity.xr.legacyinputhelpers": "1.0.0"

の設定を manifest.json の一番下に追記することで暫定対応。

理由を詳しく追えていませんが、どうも AR Foundation(ARKit/ARCore のマルチプラットフォーム AR 環境)関連の問題のようなので、Unity のアップデートでいずれ対応されると思います。

AR Foundation についてはこちらが参考になりました。

tsubakit1.hateblo.jp

それでは気を取り直して

特定の緯度経度にプレハブを配置

大崎駅付近 (35.619707, 139.7283495) に適当なプレハブを表示したいと思います。

f:id:korechi:20190521170006p:plain:h400

  1. GENERAL タブ内の Location を 35.619707, 139.7283495
  2. MAP LAYERSData SourceMapbox Streets With Building Ids
  3. POINTS OF INTEREST 内の Add Layer をクリックしてレイヤーを追加
  4. 追加されたレイヤを選択して Prefab を適当なものに設定
  5. Prefab LocationsFind byAddress Or Lat Lon にして Add Location をクリック
  6. Location 035.619707, 139.7283495 を指定
  7. 実行

f:id:korechi:20190521170603p:plain

大崎駅にピンをたたせることができました!

これを応用すればポケストップを表示する、なんてこともできそうですね。

建物を立体的に

3D地図っぽい感じに建物を立体的にのばしてみたいと思います。

f:id:korechi:20190521171402p:plain:h200

  1. MAP LAYERSData SourceMapbox Streets With Building Ids に(さっきのまま)
  2. FEATURESAdd Feature をクリックして Map Features が追加
  3. Data Layerbuilding
  4. 実行

f:id:korechi:20190521171457p:plain

デフォルトの設定でここまで表示できるのは良いですね。

建物の外観は TexturingStyle Type から変更可能です。例えば Style TypeColor にすると

f:id:korechi:20190521171811p:plain:h200

f:id:korechi:20190521171841p:plain

こんな風に変えることができます。

Mapbox の簡単な使い方はおさらいできたので、今回はここまで。次はもう少し詳しくドキュメントを読んで遊んでみたいと思います。

ProjectNorthStar を 6DoF 化してみる

もう他の記事でも紹介されているかもしれませんが自分のメモも兼ねてまとめておきます。

前回の記事で ProjectNorthStar を組み立てました。

korechipostit.hatenablog.com

ただし ProjectNorthStar で使われる LeapMotion は手の認識のみを行うため AR グラスを作ったからといって 6DoF 機能はありません。

つまり ProjectNorthStar だけでは AR のオブジェクトを現実空間に定位させることができないということですね。

でもそれだとできることに制限がありますし HoloLens みたいに空中に AR オブジェクトを固定したいなと。そこで SLAM が可能な RealSense T265 を組み合わせることで今回 ProjectNorthStar を 6DoF 化させてみました!

見た目はこんな感じ。上に乗っかっているのは RealSense。

f:id:korechi:20190310235358j:plain:h400

作ったデモ

費用

  • ProjectNorthStar
    • 23,176円
      • 内訳:9396(LeapMortion)+1480(ヘッドギア)+1080(ネジ)+2980*2(ディスプレイ)+5046(リフレクター)+547(HDMIケーブル)
  • realsense
    • 25,035円

これを安いと見るか高いと見るかは人それぞれですが、自分はこれで SLAM 可能な AR グラスが自作できるのなら安いかなと思います。

それでは実際に Unity での実装手順を紹介します。

ただしその前に Intel RealSense SDK を PC にインストールしておきましょう。現状 Mac 等の OS には対応していないため Windows マシンにインストールします。(LeapMotion の Orion SDKWindows のみサポートなのでどのみち Windows を使います)

software.intel.com

SDK をインストールすると RealSense 用 Viewer が使えるようになるため、まずはそれで RealSense の自己位置がとれているか確認してみましょう。

ちょっと触ってみましたが、これだけでもすごい!

実装手順

とりあえず詳しい説明は省き、とりあえず 6DoF 化させたい!という人のために、必要最小限の工数で 6DoF 化するための手順を紹介します。

  1. realsense.unitypackage を Unity へインポート github.com
  2. LeapAR.unitypackage を Unity へインポート github.com
  3. LeapAR のシーンをベースに作業を進めるため LeapMotion/Norrth Star/Scenes/NorthStar.scene シーンを開き、別名として保存(test.scene とでもしておきます)
  4. 次に realsense の自己位置を取得するため RealSenseSDK2.0/Scenes/Samples/SLAM.scene シーンを開き hierarchy にある RsDevicePose を Prefab 化 f:id:korechi:20190311002049p:plain
  5. 先ほど保存した test.scene を開き Prefab 化した RsDevicePose を hierarchy に配置
  6. ここの Pose オブジェクトの position と rotation は現実での LeapMotion と RealSense 間の相対位置に合うように調整
  7. 相対位置が良い感じになったら ARCameraRig を Pose オブジェクトの子オブジェクトに
  8. Pose オブジェクトの Inspector 内の RsPoseStreamTransform の Source に RsDevice オブジェクトをアタッチ
  9. 最後に適当なオブジェクト(今回は Cube)を目の前に表示されるように配置して実行 f:id:korechi:20190311002625p:plain

視界の目の間に Cube が表示され、移動すると Cube の見え方が変わるのが確認できるはずです!

Tips

RealSense は裏にねじ穴があるので、比較的折れ曲がりにくい紙を挟んで固定し、下をちょっとはみ出させればうまいこと LeapMotion の裏にさしこむことができます。(ネジは3M*5Bを使用)

f:id:korechi:20190312200147j:plain:h400

f:id:korechi:20190312200335j:plain:h400

ProjectNorthStar を組み立ててみた

公開されている 3D モデルを印刷し、いくつかの部品を揃えれば自作できる AR グラスこと、ProjectNorthStar を作ってみました!

github.com

完成させるために21000円程度かかりました。これで自作 AR グラスが作れると思えば意外と高くないかも?

完成品 f:id:korechi:20190307235346j:plain

手を認識するデモ

youtu.be

参考にした記事

tech.showroom.co.jp

exiii.jp

psychic-vr-lab.com

作り方はこれらの記事にわかりやすく書かれているため割愛します。

Tips

外部ディスプレイの設定は忘れがち&情報が少なかったのでメモ。

ProjectNorthStar に向かって左が第2ディスプレイ(縦)で右が第3ディスプレイ(縦の反転)です。

f:id:korechi:20190307235744j:plain

また、ProjectNorthStar をかけると前方部が垂れ下がってしまったため紐で縛りました。

f:id:korechi:20190308000348j:plain:h400

コード類もまず左右でまとめて、最後に後ろで縛ると取り扱いがしやすくなります。

f:id:korechi:20190308000724j:plain:h400

また、↓を買うと HDMI が固定されやすくなりおすすめです。

https://www.amazon.co.jp/gp/product/B0747675WN/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

SharingWithUNET サンプルでクライアント側のみ弾が前へ進まない問題

HoloToolkit-Unity-Example にある SharingWithUNET サンプルを実機で動作させたらクライアント側でのみ弾が前に進まなず空中で静止するバグ?を発見(サーバ側では弾がちゃんと前に進む)

その原因となる問題のコードがこちら

  • MixedRealityToolkit-Unity/Assets/HoloToolkit-Examples/SharingWithUNET/Scripts/PlayerController.cs github.com
        [Command]
        void CmdFire()
        {
            Vector3 bulletDir = transform.forward;
            Vector3 bulletPos = transform.position + bulletDir * 1.5f;

            // The bullet needs to be transformed relative to the shared anchor.
            GameObject nextBullet = (GameObject)Instantiate(bullet, sharedWorldAnchorTransform.InverseTransformPoint(bulletPos), Quaternion.Euler(bulletDir));
            nextBullet.GetComponentInChildren<Rigidbody>().velocity = bulletDir * 1.0f;
            NetworkServer.Spawn(nextBullet);

            // Clean up the bullet in 8 seconds.
            Destroy(nextBullet, 8.0f);
        }

        public void OnInputClicked(InputClickedEventData eventData)
        {
            if (isLocalPlayer)
            {
                CmdFire();
            }
        }

NetworkServer.Spawn(nextBullet); でクライアント側でも球が表示されるわけですが、velocity はクライアント側に引き継がれませんのでクライアント側でも別に velocity を与えてあげる必要があります

そこでクライアント側ではクライアント側で Instantiate をした object に対して velocity を与えてあげる RpcShoot() をサーバでの処理である CmdFire() のあとに呼び出します

       [Command]
        void CmdFire()
        {
            Vector3 bulletDir = transform.forward;
            Vector3 bulletPos = transform.position + bulletDir * 1.5f;

            // The bullet needs to be transformed relative to the shared anchor.
            GameObject nextBullet = (GameObject)Instantiate(bullet, sharedWorldAnchorTransform.InverseTransformPoint(bulletPos), Quaternion.Euler(bulletDir));
            nextBullet.name = "Bullet";
            Vector3 velocity = bulletDir * 5.0f;
            nextBullet.GetComponentInChildren<Rigidbody>().velocity = velocity;
            NetworkServer.Spawn(nextBullet);
            RpcShoot(nextBullet, velocity);

            // Clean up the bullet in 8 seconds.
            Destroy(nextBullet, 8.0f);
        }

        [ClientRpc]
        void RpcShoot(GameObject obj, Vector3 velocity)
        {
            obj.GetComponentInChildren<Rigidbody>().velocity = velocity;
        }

これで無事にクライアント側でも弾が出現した後に前へ進むようになりました

Docker で openAI の gym 環境を作って強化学習サンプルを試してみた

目的

  • Docker のお勉強
  • openAI をお試し
    • とりあえず動くところまで!

開発環境

Windows 10 Pro

Docker 環境構築

qiita.com

ここを参考にしました。 ただし CPU 仮想化が無効になっていたので BIOS モードで起動して CPU 仮想化を有効にする必要がありました。

Docker を使った openAI/Gym の環境構築

https://hub.docker.com/r/eboraas/openai-gym/

今回これを使います。 スターもいくつかついているし良さそう。Windows PowerShell で以下のコマンドを叩いて Docker イメージをプル。

$ docker pull eboraas/openai-gym

Docker コマンドの簡単な使い方はここらへんを参考に。

qiita.com

qiita.com

Jupyter Notebook を使うことで インタラクティブに openAI のコードを試すことができるため、いくつか引数を指定します。

$ docker run -d -p 8888:8888 -p 6006:6006 -v /path/to/notebooks/:/mnt/notebooks/ eboraas/openai-gym

コンテナがたちあがったら http://localhost:8888 にブラウザでアクセスして Jupyter Notebook を閲覧できます。

python2 の notebook を作成して「Shift + Enter」で実行してみます。

Jupyter の使い方は以下を参考にしました。

Jupyterを使ってみた - Qiita

f:id:korechi:20181105113508p:plain

動いた!!!!

公式ドキュメントにあがっているサンプルコードだと Jupyter 上で実行してもウインドウが立ち上がらないため、一部書き換えました。

import gym
from IPython import display
import matplotlib.pyplot as plt
%matplotlib inline

env = gym.make('Breakout-v0')
env.reset()
for _ in range(1000):
    plt.imshow(env.render(mode='rgb_array'))
    display.clear_output(wait=True)
    display.display(plt.gcf())
    env.step(env.action_space.sample())

python3 の Notebook が作れないのが気になりますが今回はここまでとします。