見出し画像

Niantic Lightship VPS の実装方法

はじめに

Niantic Lightship VPS の実装方法について説明します。


OnePlanet XR について

https://1planet.co.jp/xrconsulting.html

このブログ記事は OnePlanet XR によるものです。
OnePlanet XR は、AR/MR/VPS技術に専門特化したコンサルティングサービスです。豊富な実績を元に、AR/MR技術を活用した新たな事業の立ち上げ支援や、社内業務のデジタル化/DX推進など、貴社の必要とするイノベーションを実現いたします。

ご相談から受け付けております。ご興味ございましたらお問い合わせください。


Niantic Lightship VPS 

Niantic Wayfarer beta でアクティベートしたVPSのスキャンデータをアプリに取り込んで表示するデモアプリを作成します。


開発環境 / 動作環境

Unity Editor 2020.3.28f1
Lightship ARDK for Unity 2.4.1
iPhone 12 Pro


事前準備

プライベートVPSの場合

LiDAR搭載のiOSデバイスにNiantic Wayfarer betaをインストールを行い、
VPSで使用する場所の3DスキャンからVPSアクティベートまで実施します。(アクティベートまで4時間以上待つ必要があります。)

パブリックVPS(Wayspot)の場合

Niantic Wayfarer beta 上でVPSで使用するWayspotのVPSがアクティベートが完了していない場合、Niantic Wayfarer betaを使って3Dスキャンの実施とアップロードを行う必要があります。(10回以上の3Dスキャンデータのアップロードを行う必要があり、アクティベートまで数時間待つ必要があります。)

Geospatial Browser から3Dスキャンデータのダウンロード

VPSで使用する場所がアクティベート済であれば、以下のように表示されます。使用するVPSの3Dスキャンしたメッシュをダウンロードします。(FBXファイル、JPEGファイル、JSONファイルを圧縮したZIPファイルがダウンロードされます。

https://lightship.dev/account/geospatial-browser/

ヒエラルキー

ARSceneManager

シーンを新規作成します。Main Cameraは削除し、ARSceneManagerのプレファブをヒエラルキーに配置します。

VPSDemo

Game Objectを作成し、名前を VPS Demo にします。
新規でスクリプトを作成します。
名前はVPSDemoとし、VPS Demo のGame Objectに追加します。
コードは以下になります。

using UnityEngine;
using Niantic.ARDK;
using Niantic.ARDK.AR;
using Niantic.ARDK.AR.ARSessionEventArgs;
using Niantic.ARDK.AR.WayspotAnchors;
using Niantic.ARDK.Extensions;
using Niantic.ARDK.LocationService;

public class VPSDemo : MonoBehaviour
{
    private WayspotAnchorService WayspotAnchorService;
    private IARSession _arSession;

    private IWayspotAnchorsConfiguration _config;

    [SerializeField]
    private GameObject _anchorPrefab;

    [SerializeField]
    private string _anchor_b64String;

    private bool _isAnchor = false;

    void Start()
    {
        ARSessionFactory.SessionInitialized += HandleSessionInitialized;
    }

    private void OnDestroy()
    {
      if (WayspotAnchorService != null)
      {
        WayspotAnchorService.LocalizationStateUpdated -= LocalizationStateUpdated;
        WayspotAnchorService.Dispose();
      }
    }

    private void HandleSessionInitialized(AnyARSessionInitializedArgs args)
    {
      _arSession = args.Session;
      _arSession.Ran += HandleSessionRan;
      ARSessionFactory.SessionInitialized -= HandleSessionInitialized;
    }

    private void HandleSessionRan(ARSessionRanArgs args)
    {
      _arSession.Ran -= HandleSessionRan;
      WayspotAnchorService = CreateWayspotAnchorService();
      WayspotAnchorService.LocalizationStateUpdated += OnLocalizationStateUpdated;
    }

    private WayspotAnchorService CreateWayspotAnchorService()
    {
      var locationService = LocationServiceFactory.Create(_arSession.RuntimeEnvironment);
      locationService.Start();
      if (_config == null)
      {
        _config = WayspotAnchorsConfigurationFactory.Create();
      }
      var wayspotAnchorService = new WayspotAnchorService(_arSession, locationService, _config);
      wayspotAnchorService.LocalizationStateUpdated += LocalizationStateUpdated;
      return wayspotAnchorService;
    }

    private void OnLocalizationStateUpdated(LocalizationStateUpdatedArgs args)
    {
      Debug.Log("Localization status: " + args.State);
    }

    private void LocalizationStateUpdated(LocalizationStateUpdatedArgs args)
    {
      if (_isAnchor)
      {
        return;
      }
      if (args.State == LocalizationState.Localized)
      {
        WayspotAnchorPayload payload = WayspotAnchorPayload.Deserialize(_anchor_b64String);
        if (payload != null)
        {
          WayspotAnchorPayload[] payloads = {payload};
          var anchor = WayspotAnchorService.RestoreWayspotAnchors(payloads);
          if (anchor != null)
          {
            CreateWayspotAnchorGameObject(anchor[0], new Vector3(0, -100, 0), Quaternion.identity, true);
            _isAnchor = true;
          }
          else
          {
            Debug.LogError("Anchor is NULL");
          }
        }
        else
        {
          Debug.LogError("Payload is NULL");
        }
      }
    }

    private void CreateWayspotAnchorGameObject
    (
      IWayspotAnchor anchor,
      Vector3 position,
      Quaternion rotation,
      bool startActive
    )
    {
      var go = Instantiate(_anchorPrefab, position, rotation);
      var tracker = go.GetComponent<WayspotAnchorTracker>();
      if (tracker == null)
      {
        tracker = go.AddComponent<WayspotAnchorTracker>();
      }

      tracker.gameObject.SetActive(startActive);
      tracker.AttachAnchor(anchor);
    }
}

ダウンロードした3DスキャンデータをUnityにインポート

ダウンロードした3DスキャンデータのZIPを解凍します。その後、全てのファイルをインポートします。

3Dスキャンデータのプレファブを作成

ヒエラルキー上で新規GameObjectを作成します。名前はAnchorとします。
Anchorの配下にインポートした3DスキャンデータのFBXファイルを配置します。(ダウンロードしたデータによって、インポートした3DスキャンデータのFBXファイルのPositionやRotationの調整が必要になります。インポートしたJPEGファイルをヒエラルキー上にある3Dモデルにドラッグ&ドロップすると反映されます。)

ヒエラルキーにあるAnchorをPrefab化。その後、ヒエラルキー上にあるAnchorのGame Objectを削除します。


VPSDemoのフィールド設定

VPSDemoのAnchor Prefab には、プレファブ化したAnchorを設定します。
次にインポートしたJSONファイルを開き、AnchorPayload の値をコピーします。その後、VPSDemoのAnchor_b64 StringにコピーしたAnchorPayloadの値を設定します。


設定

CameraとLocationを使用するため以下のようなテキスト情報を設定します。


実行

VPSをアクティベートした場所で起動するとローカライズ(8秒〜10秒)され、スキャンした3Dモデルが表示されます。


OnePlanet XR

https://1planet.co.jp/xrconsulting.html

AR/MR/VPS技術に専門特化したコンサルティングサービス

Niantic Lightship VPS 、 Immersal、Snap LocationAR、Google Geospatial APIを使ったソリューションのご検討の方からのお問い合わせ、お待ちしております。


お問い合わせ先

https://1planet.co.jp/xrconsulting.html#op_form


OnePlanet Tech Magazine

Magic Leap1 、Magic Leap2、スマホAR(Niantic Lightship ARDK、WebAR、VPSなど)といったAR技術全般をブログマガジンを連載しています。