yotiky Tech Blog

とあるエンジニアの備忘録

HoloLens2 でQRコードのスキャンを実装する(位置検知編)

今回は、QRTracking を参考に位置検知を実装します。

最新のコードは実際に扱うには問題が含まれています。 以前は Legacy XR で実装されていましたが、6/18 のコミットで Unity 2019 へバージョンアップするとともに XR Plugin での実装に更新されています。こちらはアプリを実行とすると焦点があっていない現象が起きホログラムが二重に見えます。位置検知なので正確性は目で見て判断できません。

HoloLens と XR Plugin の問題なのか、QRに関することが絡んでいるのか、未調査です。また、同じような現象で Issue もたったるようなので要観察です。

github.com

キャプチャだとだいぶずれてますが、実際は大体合ってます。二重に見えるので大体です。。

f:id:yotiky:20201024222358j:plain

というわけで、Legacy XR 版を参考にしましょう。unity2018-old ブランチを参考にしてください。

目次

検証環境

  • Unity:2019.4.3f1
  • VisualStudio:2019
  • MRTK 2.5 (設定、UI、操作などに)
  • UniRx

手順

導入~基本的なスキャン実装

  • スキャン実装までの手順は前回の記事を参照してください
  • 以下、XR Plugin版の追加手順
    • [Package Manager] から [Windows XR Plugin] をインストール
    • [Project Settings] > [XR Plug-in Management] > [Universal Windows Platform settings] タブで、Plug-in Providers の Windows Mixed Reality にチェックをつける
    • MixedRealityToolkit のプロファイルを DefaultXRSDKConfigurationProfile に変更する
      • もしくはマニュアルで必要な設定をする
      • Spatial Awareness をOFFるか非表示にしたり、Camera のRender from PV Camera を有効にしたり
      • Legacy XR を使っていた場合は、Player Settings で当該部分をクリアにする(勝手になるかも)

実装

QRTracking のプロジェクトから SpatialGraphCoordinateSystem クラスを拝借します。(MIT ライセンスなのでファイルの先頭にコメントつけるなど) 先に書いた通り Legacy XR を使う場合は、Unity2018-old ブランチを参照してください。(直リン

SpatialGraphCoordinateSystem は、QRCode で上がってくる SpatialGraphNodeId を設定すると、くっついてる GameObject をよしなに配置してくれるようです。

よしなに配置する際の Position の中心はQRコードの左上になります。テキストやQRをオーバーレイするオブジェクトを配置する場合は、位置とサイズの調整が必要になってきます。QRCode では PhysicalSideLength が取得できるのでこれを位置とサイズに使います。

f:id:yotiky:20201024223934p:plain

まず Hierarchy の設定です。 オブジェクトの階層はこんな感じにしています。QRScanner は前回のサンプルコードと同等のものです。QRVisualizer は後ほど。

f:id:yotiky:20201024221701p:plain

QRCode には先程の SpatialGraphCoordinateSystem が追加されています。Rotation で180度回転させてこちら向きにしています。QRTracking プロジェクトを参考にしていますが、おそらく SpatialGraphCoordinateSystem で調整される際に180度回転するため、エディタ上で実際に見える向きにしてあるのだと思われます。

f:id:yotiky:20201024221851p:plain

Cubeはオーバーレイ用の板です。今回はCubeのZを薄くしたものを使っています。 Textはそのままだと上下反転しているので、180度回転させます。また、Scale とフォントサイズは適切に設定します。Position は後でスクリプトから調整するので編集用の値です。

f:id:yotiky:20201024223020p:plain

続いて QRVisualizer のコードです。

public class QRVisualizer : MonoBehaviour
{
    public GameObject qrCodePlane;
    private SpatialGraphCoordinateSystem spatialGraph;
    private GameObject plane;
    private TextMeshPro data;
    private QRScanner qRScanner;

    void Start()
    {
        spatialGraph = qrCodePlane.GetComponent<SpatialGraphCoordinateSystem>();
        plane = qrCodePlane.transform.Find("Cube").gameObject;
        data = qrCodePlane.transform.Find("Text").GetComponent<TextMeshPro>();

        qRScanner = GetComponent<QRScanner>();
        qRScanner.OnScanned
            .Subscribe(qr =>
            {
                qrCodePlane.SetActive(true);
                spatialGraph.Id = qr.SpatialGraphNodeId;
                plane.transform.localPosition = new Vector3(qr.PhysicalSideLength / 2, qr.PhysicalSideLength / 2, 0);
                plane.transform.localScale = new Vector3(qr.PhysicalSideLength, qr.PhysicalSideLength, 0.001f);
                data.text = qr.Data;
                data.gameObject.transform.localPosition = new Vector3(qr.PhysicalSideLength / 2, qr.PhysicalSideLength / 2, -0.001f);
            })
            .AddTo(this);
        qRScanner.IsReady
            .Where(x => x)
            .First()
            .Subscribe(_ => qRScanner.StartScan())
            .AddTo(this);

        qrCodePlane.SetActive(false);
    }
}

サンプルプロジェクト

ソースコード一式は以下においてあります。

github.com

関連記事

yotiky.hatenablog.com

yotiky.hatenablog.com