なんかいろいろしてみます

Nov 13, 2017 - 2 minute read - HoloLens

HoloLensのWorldAnchorについて

HoloLensで利用できる空間にオブジェクトを固定する機能「WorldAnchor」に機能紹介と使い方について書いてます.

WorldAnchorとは

HoloLensではWorldAnchorと呼ばれる現実空間上に3Dオブジェクトを固定する機能があります. HoloLensは起動時から現実空間のメッシュ形状(Spatialmap)を取得,更新しています. SpatialmapはHoloLens自身の位置を特定するために利用され,接続されているWifi情報に紐づけられて記録されています. 次回起動時には接続Wifiに紐づけられたSpatialmapを呼び出すことで素早く自己位置の特定が行えます. WorldAnchorは上記のSpatialmap情報を用いることで設置されたオブジェクトの位置を固定することができます. 再起動した場合でも同一環境,Wifiに接続できれば自動的に設置場所を探して再設置してくれます.

HoloLensのスタートメニューから設置した2DアプリもWorldAnchorにより室内に固定されています.

HoloLensのDevicePortalからは実際に室内に設置したWorldAnchorを確認することもできます.

  • DevicePortalの3DViewを表示
  • View optionsよりShow spatial anchorsにチェックを入れる
  • Spatial mappingのUpdateで室内のWorldAnchorを座標軸のモデルで確認できます

今のところ設置されたWorldAnchorをDevicePortal上から移動,削除はできないようです.

UnityでWorldAnchorを使う

UnityではHoloLens用にWorldAnchorを利用するための関数が準備されています.

WorldAnchor : オブジェクトをコントロールするクラス

WorldAnchorStore : WorldAnchor全体をコントロールするクラス

以下の関数はHoloLens用のためそれ以外では機能しません. またUnity5.6,2017.1系とUnity2017.2ではnamespaceが変更されており,利用されるバージョンによって参照usingが異なっています. 幸いなことに利用する関数名はバージョンが異なっていても同一のため

using UnityEngine.VR.WSA;
using UnityEngine.XR.WSA;
に変更するだけで対処できます(やさしい).

 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.WSA;
using UnityEngine.XR.WSA.Persistence;

// オブジェクトのWorldAnchorコントロール
public class WorldAnchorControl : MonoBehaviour
{
    public bool SetOnAwake = false;
    public bool DestroyAnchorClear = false;// 再起動時に位置を復帰させる場合false
    private WorldAnchorStore anchorstore = null;

    void Start()
    {
        WorldAnchorStore.GetAsync((store)=> {
            anchorstore = store;
            string[] ids = anchorstore.GetAllIds();
            for (int i = 0; i < ids.Length; i++)
            {
                if (ids[i] == gameObject.name)
                {
                    anchorstore.Load(gameObject.name, gameObject);
                    break;
                }
            }
            if (SetOnAwake) SetWorldAnchor();
        });
    }

    void OnDestroy()
    {
        if (DestroyAnchorClear) DeleteWorldAnchor();
    }

    public void SetWorldAnchor()
    {
        DeleteWorldAnchor();
        if (anchorstore != null)
        {
            WorldAnchor worldanchor = gameObject.AddComponent<WorldAnchor>();
            worldanchor.name = gameObject.name;
            if (worldanchor.isLocated) anchorstore.Save(worldanchor.name, worldanchor);
            else worldanchor.OnTrackingChanged += OnTrackingChanged;
        }
    }

    private void OnTrackingChanged(WorldAnchor self, bool located)
    {
        if (located)
        {
            anchorstore.Save(self.name, self);
            self.OnTrackingChanged -= OnTrackingChanged;
        }
    }

    public void DeleteWorldAnchor()
    {
        if (anchorstore != null)
        {
            WorldAnchor worldanchor = gameObject.GetComponent<WorldAnchor>();
            if (worldanchor != null)
            {
                anchorstore.Delete(worldanchor.name);
                DestroyImmediate(worldanchor);
            }
        }
    }

    // WorldAnchorの全体削除
    public void AllClearWorldAnchor()
    {
        if (anchorstore != null) anchorstore.Clear();
    }
}

基本的にWorldAnchorの管理はWorldAnchorStoreにて行います. WorldAnchorStoreでWorldAnchorの呼び出し(Load),保存(Save),削除(Delete)を行っています. またWorldAnchorStoreで管理しているすべてのWorldAnchorの削除(Clear)も行えます.

WorldAnchorは各GameObjectにアタッチすることでGameObjectの位置を固定できます. アタッチされたGameObjectの位置はWorldAnchorが操作するようになるため移動することはできません. 移動する場合は一旦WorldAnchorを削除して,移動後に再度WorldAnchorをアタッチする必要があります. WorldAnchorはWorldAnchorStoreが削除を行わず起動時に再設置の処理を行えば,現実空間の同じ場所にオブジェクトを復帰させることができます(便利).

つらいところ

うまく復帰しないです.

  • 位置がずれる
  • 壁に埋まる
  • どこかに飛ぶ

  • 原因

    • HoloLensが認識しているSpatialmapの情報をもとに再設置を行っているため
    • 現実の物体が移動すればmapは変わる
    • 人が行き来すればmapは変わる
    • そもそもHoloLensの位置が変われば取得できるmapも異なる
  • 対策

    • 適度に特徴点が存在する場所を選ぶ(物,模様がある)
    • 現実のものは動かさない
    • HoloLensの正面で人が行き来するようにしない
    • HoloLensのアプリ開始地点は決めておく
    • アプリ起動前にHoloLensで見る場所はあらかじめSpatialmapを取得しておく

まとめ

HoloLensでWorldAnchorを使う場合は体験スペースも込みで作った方が安定しそう.