Skip to main content
Version: 20 Mar 2024

Localization Map Overview

This guide provides a comprehensive overview of the MLSpace API, specifically focusing on the key features and functions used to manage MLSpaces in your applications. It covers topics such as subscribing to the OnLocalizationEvent to monitor localization status changes, fetching available spaces, understanding and getting localization results, localizing into a specific space, and the export and import of spaces. Each topic is explored with detailed explanations and illustrative code snippets, aiming to provide a clear understanding of how to leverage the MLSpace API effectively. The guide offers insights into the usage of key structs, values, and enums, enhancing your ability to create more interactive and responsive applications using MLSpaces.

caution

This feature requires the Magic Leap 2 Localization Maps OpenXR Feature to be enabled in your project's OpenXR Settings (Window > XR Plugin Manager > OpenXR Settings).

Localization Events

Developers can turn Localization Events on or off using the EnableLocalizationEvents method. Localization events can be obtained once enabled by passing true to the method.

public XrResult EnableLocalizationEvents(bool enableEvents);

There are two different ways to receive the events:

  • Developers can call GetLatestLocalizationMapData to get the latest events directly.

  • Subscribe to OnEventDataLocalizationChangedCallback to receive a callback when events occur.

Both methods provide the same LocalizationEventData so developers can choose according to their preferences and application needs.

LocalizationEventData

The LocalizationEventData struct provides detailed information about the device's localization in a Space. This information is valuable when you need to understand whether the device is localized in a specific Space, and if so, which one.

PropertyTypeDescription
StateLocalizationMapStateThe status of the localization. This is an enum which can either be NotLocalized,Localized LocalizationPending, SleepingBeforeRetry, indicating whether the device is currently localized to an MLSpace.
MapLocalizationMapThe Space to which the device is localized, if it is it will contain the details of the MLSpace to which the device is localized.
ConfidenceLocalizationMapConfidenceThe confidence of the the device's current localization. This can be Poor, Fair, Good or Excellent
ErrorsLocalizationMapErrorFlags The localization error that occurred if the device could not localize. This can be UnknownBit, OutOfMappedAreaBit, LowFeatureCountBit, ExcessiveMotionBit, LowLightBit, or HeadposeBit

Examples

There are two primary ways to get a EnableLocalizationEvents. In both of these examples, if the device is localized, the State property of the LocalizationEventData provides will be equal Localized.

MLSpace On LocalizationChanged callback

The OnLocalizationChanged event is invoked when the localization status of the device changes. Subscribing to this event provides an easy way to receive updates about the localization status.


private MagicLeapLocalizationMapFeature localizationMapFeature = null;

void Start()
{
// Obtain the instance of the localization Map Feature
localizationMapFeature = OpenXRSettings.Instance.GetFeature<MagicLeapLocalizationMapFeature>();
// If it is not present return
if (localizationMapFeature == null || !localizationMapFeature.enabled)
{
Debug.LogError("Magic Leap Localization Map Feature does not exists or is disabled.");
return;
}

// Enable the localization Events
XrResult result = localizationMapFeature.EnableLocalizationEvents(true);
if (result != XrResult.Success)
{
Debug.LogError($"Failed to enable localization events with result: {result}");
return;
}

MagicLeapLocalizationMapFeature.OnLocalizationChangedEvent += OnLocalizationChanged;
}

void OnLocalizationChanged(MagicLeapLocalizationMapFeature.LocalizationEventData data)
{
Debug.Log($"Localization Status: {data.State}");
if (data.State == MagicLeapLocalizationMapFeature.LocalizationMapState.Localized)
{
Debug.Log($"Localized to space: {data.Map.Name}");
}
}

Query Localization using GetLatestLocalizationMapData

The GetLatestLocalizationMapData method can be used to query the current localization status at any point. The function will return true if the localization status changed the LocalizationResult was retrieved successfully.


private MagicLeapLocalizationMapFeature localizationMapFeature = null;

void Start()
{
// Obtain the instance of the localization Map Feature
localizationMapFeature = OpenXRSettings.Instance.GetFeature<MagicLeapLocalizationMapFeature>();
// If it is not present return
if (localizationMapFeature == null || !localizationMapFeature.enabled)
{
Debug.LogError("Magic Leap Localization Map Feature does not exists or is disabled.");
return;
}

// Enable the localization Events
XrResult result = localizationMapFeature.EnableLocalizationEvents(true);
if (result != XrResult.Success)
{
Debug.LogError($"Failed to enable localization events with result: {result}");
return;
}

MagicLeapLocalizationMapFeature.OnLocalizationChangedEvent += OnLocalizationChanged;
}

LocalizationMap

The LocalizationMap structure represents a saved map of a physical environment, known as a Space, on a Magic Leap device.

PropertyTypeDescription
MapUUIDstringThe unique identifier for the Space.
NamestringThe human-readable name of the Space.
MapTypeLocalizationMapType Identifies if the Space is on device or AR Cloud.

Get List Of Available Spaces Example

Developers can retrieve a list of all available maps by calling GetLocalizationMapsList. The returned list includes both OnDevice and ARCloud maps, which are distinguished by the LocalizationMapType field in the LocalizationMap struct. While there is support for passing query info header to filter the results, the feature isn't fully completed as of yet.

void GetListOfAvailableSpaces()
{
// Verify that the localization Map Feature is present
if (localizationMapFeature == null || !localizationMapFeature.enabled)
return;

// Get the list of spaces
var result = localizationMapFeature.GetLocalizationMapsList(out MagicLeapLocalizationMapFeature.LocalizationMap[] maps);
if (result == XrResult.Success)
{
// ...
}
}

Localize Into a Map Example

The RequestMapLocalization(string mapId) function requests to localize the device to a specific Space. The function requires the mapId of the Space for localization. This is an asynchronous request. Use GetLatestLocalizationMapData function to get the LocalizationEventData of the localization or use the MagicLeapLocalizationMapFeature.OnLocalizationChangedEvent to listen to the localization events.

A new request for localization will override all the past requests for localization that are yet to be completed.

Required Namespaces
using System;
using UnityEngine;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features.MagicLeapSupport;
Localize to Space Example
   public void LocalizeMap()
{
if (localizationMapFeature == null || !localizationMapFeature.enabled)
return;
string mapUUID = "YOU_SPACE_ID_HERE";
var result = localizationMapFeature.RequestMapLocalization(mapUUID);
Debug.Log($"Localize request result: {result}");
}

Export Map

The ExportLocalizatioMap(...) function exports a Map into a binary data format that can be saved and later used for import. The ExportSpace method requires the unique map ID of the Map you want to export. If the call is successful, the call returns a byte array of the exported map.

ParameterDescription
stringmapIdThe unique map ID of the map you want to want to export.
out byte[] mapDatabyte array of the exported map.

Permissions

Before the ExportSpace method can be used, the com.magicleap.permission.SPACE_IMPORT_EXPORT permission must be requested at runtime. Without this permission, the function call will fail.

Export Space Example

Here's an example of how to use the ExportSpace method to export a MLSpace and save it to a file:

Required Namespaces
using System;
using System.IO;
using UnityEngine;
using UnityEngine.XR.MagicLeap;
using UnityEngine.XR.MagicLeap.Native;
Export Space Example

public void ExportSpace()
{
if (localizationMapFeature == null || !localizationMapFeature.enabled || !permissionGranted)
return;

string mapID = "YOU_SPACE_ID_HERE";
XrResult result = localizationMapFeature.ExportLocalizatioMap(mapID, out byte[] mapData);
if (result == XrResult.Success)
{
SaveSpaceToFile(mapData);
}
}

private void SaveSpaceToFile(byte[] mapData)
{
string filePath = "YOU_FILE_PATH_HERE";
using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
{
fileStream.Write(mapData, 0, mapData.Length);
}

if (File.Exists(filePath))
{
Debug.Log("Binary data saved to file: " + filePath);
}
else
{
Debug.LogError("Failed to save binary data to file: " + filePath);
}
}
The exported MLSpace data may contain sensitive information

We recommend that developers encrypt this data before storing it to ensure the privacy and security of their users.

Import Spaces

The ImportLocalizationMap(byte[] mapData, out string mapId) function is used to import a MLSpace from a binary data format that was previously exported using the ExportLocalizatioMap() function. This function is particularly useful when you need to transfer spaces between devices.

The ImportSpace function requires two parameters:

ParameterDescription
byte[] mapDataThe binary data of the exported space. This data is usually loaded from a file or received from another device
out string mapIdIf the call is successful, the method returns a unique map ID assigned to the imported map

Permissions

In order to utilize the ImportSpace function, your application must first request and be granted the com.magicleap.permission.SPACE_IMPORT_EXPORT permission at runtime. Without this permission, the function call will fail.

Import Spaces Example

This example loads a Map from binary data using the ImportLocalizationMap function.

Required Namespaces
using System;
using System.IO;
using UnityEngine;
using UnityEngine.XR.MagicLeap;
using UnityEngine.XR.MagicLeap.Native;
Import Space Example
public void ImportSpace()
{
if (localizationMapFeature == null || !localizationMapFeature.enabled || !permissionGranted)
return;

string filePath = "/YOUR/FILE/PATH/HERE";

if (!File.Exists(filePath))
{
Debug.LogWarning("No spaces have been exported, cannot import last exported space.");
return;
}

byte[] binaryData;
using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
{
binaryData = new byte[fileStream.Length];
fileStream.Read(binaryData, 0, binaryData.Length);
}

XrResult result = localizationMapFeature.ImportLocalizationMap(binaryData, out string mapId);
if (result == XrResult.Success)
{
Debug.Log($"Space {info.SpaceId} Imported Successfully");
}
}