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 LocalizationMap 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.
using MagicLeap.OpenXR.Features.LocalizationMaps;
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.
Property | Type | Description |
---|---|---|
State | LocalizationMapState | The 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. |
Map | LocalizationMap | The Space to which the device is localized, if it is it will contain the details of the MLSpace to which the device is localized. |
Confidence | LocalizationMapConfidence | The confidence of the the device's current localization. This can be Poor , Fair , Good or Excellent |
Errors | LocalizationMapErrorFlags 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
.
Permissions
These functions require that the com.magicleap.permission.SPACE_MANAGER
permission is declared in your Application's Manifest File**. Without this permission, the function call will fail.
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(LocalizationEventData data)
{
Debug.Log($"Localization Status: {data.State}");
if (data.State == 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;
private 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}");
}
}
private void Update()
{
// Check Localization Status
LocalizationEventData data;
if (localizationMapFeature.GetLatestLocalizationMapData(out data))
{
if (data.State == LocalizationMapState.Localized)
{
Debug.Log($"Localized to space: {data.Map.Name}. Origin : {localizationMapFeature.GetMapOrigin()}");
}
else
{
Debug.Log($"Localization State: {data.State}");
}
}
}
LocalizationMap
The LocalizationMap
structure represents a saved map of a physical environment, known as a Space, on a Magic Leap device.
Property | Type | Description |
---|---|---|
MapUUID | string | The unique identifier for the Space. |
Name | string | The human-readable name of the Space. |
MapType | LocalizationMapType | Identifies if the Space is on device or AR Cloud. |
Permissions
These functions require that the com.magicleap.permission.SPACE_MANAGER
permission is declared in your Application's Manifest File**. Without this permission, the function call will fail.
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 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.
using System;
using UnityEngine;
using UnityEngine.XR.OpenXR;
using MagicLeap.OpenXR.Features.LocalizationMap;
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.
Parameter | Description |
---|---|
stringmapId | The unique map ID of the map you want to want to export. |
out byte[] mapData | byte 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:
using System;
using System.IO;
using UnityEngine;
using UnityEngine.XR.MagicLeap;
using UnityEngine.XR.MagicLeap.Native;
// To access permissions
using MagicLeap.Android;
public void ExportSpace()
{
if (localizationMapFeature == null || !localizationMapFeature.enabled || !Permissions.CheckPermission(UnityEngine.XR.MagicLeap.MLPermission.SpaceImportExport))
return;
string mapID = "YOU_SPACE_ID_HERE";
XrResult result = localizationMapFeature.ExportLocalizationMap(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);
}
}
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:
Parameter | Description |
---|---|
byte[] mapData | The binary data of the exported space. This data is usually loaded from a file or received from another device |
out string mapId | If 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.
using System;
using System.IO;
using UnityEngine;
using UnityEngine.XR.MagicLeap;
using UnityEngine.XR.MagicLeap.Native;
// To access permissions
using MagicLeap.Android;
public void ImportSpace()
{
if (localizationMapFeature == null || !localizationMapFeature.enabled || !Permissions.CheckPermission(UnityEngine.XR.MagicLeap.MLPermission.SpaceImportExport))
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 {mapId} Imported Successfully");
}
}
Complete Example
To see a complete Unity C# example of the Localization Map Feature, see the Localization Map Example page.