Skip to main content

Querying VPS Coverage for AR Locations at Runtime

The VPS Coverage API provides functionality for discovering AR Locations at runtime to display them on maps and use them as localization targets for an ARLocationManager.

Configuring the CoverageClientManager

Coverage Client Manager

CoverageClientManager can either be added to your scene in the Unity Editor or at runtime through AddComponent. It can either query for ARLocations around the user's current GPS location or one they specify (for example, remotely viewing a city on a map). CoverageClientManager also provides configuration for a QueryRadius which defines the radius (in meters) to query around the GPS location.

note

Your Unity project will need location usage permissions set up for the build target. For iOS, a Location Usage Description is required in Project Settings. For Android, the user will need to grant the ACCESS_FINE_LOCATION permission, which the CoverageClientManager will request upon use.

The following code snippet demonstrates setting up and configuring the CoverageClientManager to query for ARLocations within 1km of the user's current location.

Click to reveal CoverageClientManagerExample.cs
using Niantic.Lightship.AR.VpsCoverage;
using UnityEngine;

public class CoverageClientManagerExample : MonoBehaviour
{
[SerializeField]
private CoverageClientManager CoverageClientManager;

public void QueryAroundUser()
{
// If not provided, create one on the current gameobject
if (!CoverageClientManager)
{
CoverageClientManager = gameObject.AddComponent<CoverageClientManager>();
}

// Use the current location of the device to query coverage. The query radius is set to 1000 meters.
CoverageClientManager.UseCurrentLocation = true;
CoverageClientManager.QueryRadius = 1000;

CoverageClientManager.TryGetCoverage(OnCoverageResult);
}

private void OnCoverageResult(AreaTargetsResult result)
{
// Currently does nothing
}
}

Using Coverage Results

The AreaTargetsResult class returns information from the VPS Coverage API query. Check that the Status is Success or handle failure cases as needed. Most of the relevant data from the VPS Coverage API query will be contained in the AreaTargets list.

Area Targets and Their Contents

Each AreaTarget contains two fields, the CoverageArea and LocalizationTarget.

A CoverageArea defines a 2-dimensional polygon in real-world space where Location AR is supported. For example, the Shape property can be used to draw an overlay on a map using LatLng points, while the LocalizabilityQuality property reports the overall quality of tracking in the area.

A LocalizationTarget defines a point in real-world space where VPS localization is supported. The Name and ImageURL properties can be used to create a information card about a specific location, while the DefaultAnchor property can be passed into the ARLocationManager to start tracking.

For more information on these fields and their properties, see the API documentation.

This snippet combines CoverageArea and LocalizationTarget data to sort and filter AreaTargetsResults into a usable list:

Click to reveal the Area Targets example script
using Niantic.Lightship.AR.VpsCoverage;
using UnityEngine;

public class CoverageClientManagerExample : MonoBehaviour
{
[SerializeField]
private CoverageClientManager CoverageClientManager;

public void QueryAroundUser()
{
CoverageClientManager.TryGetCoverage(OnCoverageResult);
}

private void OnCoverageResult(AreaTargetsResult areaTargetsResult)
{
if (areaTargetsResult.Status == ResponseStatus.Success)
{
// Sort the area targets by distance from the query location
areaTargetsResult.AreaTargets.Sort((a, b) =>
a.Area.Centroid.Distance(areaTargetsResult.QueryLocation).CompareTo(
b.Area.Centroid.Distance(areaTargetsResult.QueryLocation)));

// Only consider the 5 nearest production quality areas
var maxCount = 5;
foreach (var result in areaTargetsResult.AreaTargets)
{
if (result.Area.LocalizabilityQuality != CoverageArea.Localizability.PRODUCTION)
{
continue;
}

Debug.Log($"Got a localization target: {result.Target.Name}, anchor payload: {result.Target.DefaultAnchor}");
maxCount--;
if (maxCount == 0)
{
break;
}
}
}
else
{
Debug.LogError($"Coverage query failed with status: {areaTargetsResult.Status}");
}
}
}

Downloading Hint Images

Each LocalizationTarget contains an ImageURL which points to a hosted hint image corresponding to the LocalizationTarget. This information can be used to guide users to the real-world location to localize against. The CoverageClientManager contains a few utility methods to download and create a Texture with the hint image, as in the following code snippet:

Click to reveal the hint image code snippet
using Niantic.Lightship.AR.VpsCoverage;
using UnityEngine;

public class CoverageClientManagerExample : MonoBehaviour
{
[SerializeField]
private CoverageClientManager CoverageClientManager;

public void QueryAroundUser()
{
CoverageClientManager.TryGetCoverage(OnCoverageResult);
}

private async void OnCoverageResult(AreaTargetsResult areaTargetsResult)
{
if (areaTargetsResult.Status == ResponseStatus.Success)
{
foreach (var result in areaTargetsResult.AreaTargets)
{
if (string.IsNullOrEmpty(result.Target.ImageURL))
{
continue;
}

var hintTexture = await CoverageClientManager.TryGetImageFromUrl(result.Target.ImageURL);

// Do something with the texture
}
}
else
{
Debug.LogError($"Coverage query failed with status: {areaTargetsResult.Status}");
}
}
}

Due to the performance impact of blocking on downloads and texture generation, it is recommended to call this API asynchronously. We also recommend limiting the number of images downloaded at a time rather than handling every image in the response.

Using CoverageClientManager Output in ARLocationManager

After getting a list of nearby AreaTargets, the user or application can select a specific LocalizationTarget to use as an ARLocation to track. The following example chooses the first result in the response list as the ARLocation to track.

Click to reveal the example script
using Niantic.Lightship.AR.LocationAR;
using Niantic.Lightship.AR.PersistentAnchors;
using Niantic.Lightship.AR.VpsCoverage;
using UnityEngine;

public class CoverageClientManagerExample : MonoBehaviour
{
[SerializeField]
private CoverageClientManager CoverageClientManager;

[SerializeField]
private ARLocationManager ArLocationManager;

public void QueryAroundUser()
{
CoverageClientManager.TryGetCoverage(OnCoverageResult);
}

private void OnCoverageResult(AreaTargetsResult areaTargetsResult)
{
if (areaTargetsResult.Status == ResponseStatus.Success)
{
var firstResult = areaTargetsResult.AreaTargets[0];
var anchorPayloadString = firstResult.Target.DefaultAnchor;

if (string.IsNullOrEmpty(anchorPayloadString))
{
// If this area has no anchor payload, don't do anything
// Select a different area target in a real application
Debug.LogError($"No anchor found for {firstResult.Target.Name}");
return;
}

var anchorPayload = new ARPersistentAnchorPayload(anchorPayloadString);

var locationGameObject = new GameObject();
var arLocation = locationGameObject.AddComponent<ARLocation>();
arLocation.Payload = anchorPayload;

ArLocationManager.SetARLocations(arLocation);
ArLocationManager.StartTracking();
}
else
{
Debug.LogError($"Coverage query failed with status: {areaTargetsResult.Status}");
}
}
}

Surfacing Test Scans Using CoverageClientManager

Adding Test Scans

CoverageClientManager will only surface public VPS locations around the query location. However, test scans can be manually added to CoverageClientManager to be surfaced in the AreaTargetsResult response, regardless of location. Adding the ARLocationManifest of a test scan using the CoverageClientManager PrivateARLocations array will append them to the AreaTargetsResult response as if they were queried at runtime. This allows you to use the same flow for discovering public VPS locations and private test scans.

For more information about creating and important test scans, see Managing Test Scans.

More Information