本文へスキップ

Magic Leap 2でLightshipを開発中

Magic Leap 2でLightship ARDKを使用することは、多くの点で、モバイルデバイス向けのARエクスペリエンスを開発することと同じです。 Magic Leap 2と標準的なスマートフォンではハードウェアが異なるため、いくつかの作業は異なる方法で行わなければならない。 このHow-Toでは、Unityプロジェクトにおける違いとその対処法について学びます。

前提条件

  1. このハウツーを使用する前に、他のPDFにあるMagic Leap 2 Lightshipのセットアッププロセスを完了する必要があります。
  2. このHow-ToのVPSセクションには、Unityプロジェクトにアタッチされた有効なLightship APIキーが必要です。 詳しくはセットアップページをご覧ください。
  3. この How-To のスクリプトは ARLocationManager と VPS Coverage API のエレメントを使用します。 再確認が必要な場合は、コードでロケーションARを使用する方法ランタイムでARロケーションのVPSカバレッジをクエリするを参照してください。

Magic Leap 2での再生

Unityエディターで事前に録画した映像を再生することで、LightshipのPlaybackシステムは、モバイルデバイスと同じようにMagic Leap 2上でARアプリケーションをシミュレートすることができる。

Magic Leap 2でAR体験をシミュレートする:

  1. Playback recordingを作成する前に、Magic Leap 2パッケージに含まれるプレハブLightship ML RigをARシーンに追加します。 このプレハブには、エディタの入力プロバイダがコンピュータビジョン機能を実行するためのバイナリにデータを送信するのを助けるコンポーネントが含まれています。
  2. Using the API to Record Datasets](https://lightship.dev/docs/ardk/how-to/unity/create_playback_dataset/#using-the-api-to-record-datasets)の指示に従って、再生データセットを記録してください。 **Magic Leap 2で録画を使用するには、landscapeで録画する必要があります。
  3. UnityでLightshipトップメニューを開き、Lightship Settingsを選択します。 Playback**セクションで、Dataset Pathフィールドに録音へのパスを入力します。
  4. 必要なスクリプトとコンポーネントを使用してXRシーンをセットアップし、エディターでPlayを押してレコーディングしたUnityシーンを実行します。

マジック・リープ2用なりすましロケーション

VPSはローカライズ時にGPS座標を必要としなくなったが、Coverage APIは依然としてGPS座標を必要とする。 Magic Leap 2にはGPSハードウェアが搭載されていないため、Lightshipの位置情報機能の一部を利用するには、位置情報を偽装する必要がある。 ARDKにはLightshipLocationSpoofというクラスがあり、デバイス上でロケーションサービスを開始する際に静的インスタンスとして初期化し、実行時にCoverage API機能に座標情報を渡すために使用することができる。

注意

Magic Leap 2でGPSが利用できない場合でも、位置情報の偽装を行う場合は、位置情報サービスの利用を許可する必要があります。

ARDKを使って場所を偽装する:

  1. UnityでLightshipトップメニューを開き、Spoof Locationの下のEnabledボックスをチェックします。
  2. スクリプトの先頭で、Niantic.Lightship.AR.Inputをインクルードし、位置データが適切に保存されていることを確認する:
// Add at the top of your script
using Input = Niantic.Lightship.AR.Input;
  1. メインスクリプトで、LightshipLocationSpoofオブジェクトを作成し、そのフィールドを使って、なりすましたいGPS座標を設定します。 (座標が浮動小数点数で入力されていることを確認してください!)
// Setting location coordinates
LightshipLocationSpoof.Instance.Latitude = 37.795668f;
LightshipLocationSpoof.Instance.Longitude = -122.393429f;
  1. スクリプトのこの後のどの時点でも、Inputシステムを使って座標を確認したり、変数を作成して簡単に値を渡したりすることができます:
// Location verification using the Input system
var latitude = Input.location.lastData.latitude;
var longitude = Input.location.lastData.longitude;

GPS座標が設定され、確認されたら、VPS Coverage APIで場所を照会するために使用できるはずです。 これらの値はいつでも変更できるため、異なる拠点間で素早くクエリーを行うことができる。

なりすましスクリプトの例

このスクリプト例では、GPS座標を偽装し、コードの他の部分に渡せるようにするプロセスを説明します。 これはARLocationManagerからロケーションを取り込み、どのロケーションになりすましたいかを選択する方法を提供し、次にロケーション情報をInputシステムを通してMagic Leap 2のために準備する。

クリックすると位置偽装デモスクリプトが表示されます。
// Copyright 2022-2024 Niantic.
using System.Collections.Generic;
using Niantic.Lightship.AR;
using Niantic.Lightship.AR.Loader;
using Niantic.Lightship.AR.LocationAR;
using Niantic.Lightship.AR.PersistentAnchors;
using Niantic.Lightship.AR.VpsCoverage;
using UnityEngine;
using UnityEngine.UI;

using Input = Niantic.Lightship.AR.Input;

namespace Niantic.Lightship.MagicLeap.InternalSamples
{
public class VPSLocalizationSample : MonoBehaviour
{
[SerializeField, Tooltip("The Location Manager")]
private ARLocationManager _arLocationManager;

[Header("UI")]
[SerializeField, Tooltip("The Dropdown for Persistent AR Locations")]
private Dropdown _arLocationDropdown;

[SerializeField, Tooltip("The Button to select an AR Location")]
private Button _arLocationChooseButton;

[SerializeField, Tooltip("The UI Canvas to display the AR Location Selector")]
private GameObject _arLocationUI;

[SerializeField, Tooltip("Text display for latitude and longitude")]
private Text _gpsText;

private List<ARLocation> _arLocationsDropdownItems = new List<ARLocation>();

private void OnEnable()
{
if (!LightshipSettings.Instance.UseLightshipSpoofLocation)
{
Debug.LogError
(
"Magic Leap does not provide GPS, which is neccessary for Lightship VPS. " +
"Please enable the Spoof Location feature in the Lightship Settings menu in " +
"order to try out the VPS Localization Sample."
);

return;
}

_arLocationManager.locationTrackingStateChanged += OnLocationTrackingStateChanged;

if (_arLocationManager.AutoTrack)
{
_arLocationUI.SetActive(false);
}
else
{
CreateARLocationMenu();
_arLocationUI.SetActive(true);
_arLocationChooseButton.onClick.AddListener(OnLocationSelected);
}

if (Input.location.status == LocationServiceStatus.Stopped)
{
Input.location.Start();
}

UpdateGPSText();
}

private void OnDisable()
{
_arLocationManager.locationTrackingStateChanged -= OnLocationTrackingStateChanged;
_arLocationChooseButton.onClick.RemoveListener(OnLocationSelected);
}

private void CreateARLocationMenu()
{
var arLocations = _arLocationManager.ARLocations;
foreach (var arLocation in arLocations)
{
_arLocationDropdown.options.Add(new Dropdown.OptionData(arLocation.name));
_arLocationsDropdownItems.Add(arLocation);
}

if (_arLocationsDropdownItems.Count > 0)
{
_arLocationChooseButton.interactable = true;
}
}

private void OnLocationSelected()
{
var currentIndex = _arLocationDropdown.value;
var arLocation = _arLocationsDropdownItems[currentIndex];
_arLocationManager.SetARLocations(arLocation);

var gpsLocation = arLocation.GpsLocation;
LightshipLocationSpoof.Instance.Latitude = (float)gpsLocation.Latitude;
LightshipLocationSpoof.Instance.Longitude = (float)gpsLocation.Longitude;
UpdateGPSText();

_arLocationManager.StartTracking();
}

private void OnLocationTrackingStateChanged(ARLocationTrackedEventArgs args)
{
if (!args.Tracking)
{
// We de-activate the gameObject when we lose tracking.
// ARLocationManager will not de-activate it automatically
args.ARLocation.gameObject.SetActive(false);
}
}

private void UpdateGPSText()
{
// First, check if user has location service enabled
if (!Input.location.isEnabledByUser)
{
_gpsText.text = "Location service is not enabled";
return;
}

var latitude = Input.location.lastData.latitude;
var longitude = Input.location.lastData.longitude;
var altitude = Input.location.lastData.altitude;

_gpsText.text = $"Latitude: {latitude}\nLongitude: {longitude}\nAltitude: {altitude}";
}
}
}