ArcGIS IPS is an indoor positioning system that allows you to locate yourself and others inside a building in real time. Similar to GPS, it puts a blue dot on indoor maps and uses location services to help you navigate to any point of interest or destination.
ArcGIS IPS supports:
- Wayfinding
- Location tracking and sharing
- Location data collection
- Analytics
Your app can work with ArcGIS IPS to show the device location by using an IPS-aware map or by manually creating an indoor location data source.
ArcGIS IPS provides geoprocessing tools for setting up and authoring your IPS environment in ArcGIS Pro. It also includes ArcGIS IPS Setup, a mobile app to collect radio signals from Bluetooth Low Energy (BLE) beacons inside your building(s). The mobile app can make use of an existing or new beacon infrastructure and is beacon vendor agnostic.
For more information about IPS-aware maps, see ArcGIS Pro's help section on IPS-aware maps.
IPS-aware maps
To use ArcGIS IPS in your app, you must use an IPS-aware map that conforms to the ArcGIS IPS Information Model. This model specifies components such as the following:
- Floor plan: sites, facilities, levels, and other details.
- Transitions: exits and entrances.
- Pathways: line features that the device location can snap to.
- Beacons: Bluetooth Low Energy (BLE) beacons.
For a map to be IPS-aware, the map must have one of the following:
- A connection to an Indoor Positioning Data Service set in the map properties. For information on how to create an Indoor Positioning Dataset (hosted as an Indoor Positioning Data Service), see the ArcGIS Pro help topic Indoor Positioning Datset. Also see Pro's instructions on how to create the service.
- An IPS positioning feature table named "IPS_Positioning". For detailed instructions about how to create an IPS-aware map, see Get started with ArcGIS IPS.
You should also consider the following:
-
This API supports both Wi-Fi and BLE for indoor positioning on Android devices. When using ArcGIS IPS, we recommend that you only employ one of these systems in a facility.
-
Android 9 introduced Wi-Fi scan throttling to limit the number of Wi-Fi scans. To use Wi-Fi IPS, Android devices (9 or higher) must enable developer mode and disable Wi-Fi scan throttling (Developer Options > Networking > Wi-Fi scan throttling).
-
Wi-Fi IPS is not supported on iOS devices because Apple blocks 3rd-party software from using Wi-Fi for positioning.
-
If your facility has a mix of beacon-based IPS and Apple indoors positioning, the
IndoorsLocationDataSource
will utilize the beacon-based IPS, in preference.
Indoors related classes
After you have loaded your indoor map into your app's map view, you can use the following classes to display the device's location on the map:
IndoorsLocationDataSource
- provides the device's location that you can display on an indoor map by passing theIndoorsLocationDataSource
to the map view'sLocationDisplay
. The device location is calculated from its sensor data (radio, GPS, motion sensors) using data referenced in the Indoor Positioning Data Service or data held in itsIPS
feature table. You can obtain a_Positioning IndoorsLocationDataSource
from a map'sIndoorPositioningDefinition
or you can construct it from the map'sIPS
,_Positioning Pathways
andLevels
feature tables.IndoorPositioningDefinition
- provides all the information you need to create anIndoorsLocationDataSource
.IndoorsLocationDataSourceConfiguration
- allows you to configure theIndoorsLocationDataSource
. For example, you can specify how smoothly the location moves, whether the location snaps to a pathway, or whether GNSS is used to locate the device.LocationDisplay
- displays the device’s location on top of the indoor map. As the device moves, the map view can respond by updating the position of the location symbol on the display.
Add indoor positioning to your app
An IPS-aware map contains layers to visualize indoor space and has access to indoor positioning data to determine a device's location and navigate within that space. The indoor positioning data can be stored in an Indoor Positioning Data Service or an Indoor Positioning File. To show the device location on an indoor map, you have two options:
- Use the indoor positioning definition of the map to obtain the indoor location data source. In this case the IPS-aware map must be configured with an Indoor Positioning Data Service. This is the recommended approach.
- Manually create an indoor location data source from the map's IPS positioning, pathways, and levels tables. This requires that an IPS Positioning table has been added to the map and a Positioning file has been generated.
Use the indoor positioning definition of the map
If your IPS-aware map contains a IndoorPositioningDefinition
, you can display the device location in a map by obtaining the indoor location data source from the map's indoor positioning definition. Follow these steps:
-
Load the IPS-aware map in your app. This is a web map created with ArcGIS Pro that is hosted as a portal item in ArcGIS Online or in ArcGIS Enterprise.
-
Obtain an indoor positioning definition from the loaded map's
Map::indoorPositioningDefinition()
. If this value is null, you cannot create aIndoorsLocationDataSource
using this approach. Instead, manually create the indoor location data source. -
Load the indoor positioning definition to avoid any delays when the
IndoorsLocationDataSource
is started. -
Create an
IndoorsLocationDataSource
using theIndoorPositioningDefinition
. -
Assign the
IndoorsLocationDataSource
to the map view'sLocationDisplay
. -
Start the map view's location display. The device location appears on the display as a blue dot and updates as the user moves throughout the indoor space.
Manually create an indoor location data source
If your IPS-aware map does not contain a IndoorPositioningDefinition
, you can manually create an indoors location data source by using the IPS
feature table that is stored within the map.
- IPS_Positioning feature table: Each row in the table contains an indoor positioning file that was created when the IPS environment was set up using the Generate indoor positioning file geoprocessing tool. When working with an indoor location source in your app, the most recent positioning file is used unless you specify a different one using the
Row ID
.
Optionally, you can also provide the following.
-
Row ID: A globally unique ID that identifies a row in the
IPS
feature table. The positioning file associated with this row will be used to find indoor locations. If not specified in the constructor, the positioning file from the most recent survey is used._Positioning -
Levels table: An
ArcGISFeatureTable
with information about the levels, or floors, of a building. If the table is available, theIndoorsLocationDataSource
will add theLEVEL
to the_ID Location.additionalSourceProperties()
key-value pairs. You can obtain the floor number by using thefloor
key. The ground floor has a value of 0 and floors below ground have negative values. -
Pathways table: An
ArcGISFeatureTable
with line features that represent paths through the indoor space. Locations provided by theIndoorsLocationDataSource
are snapped to the lines in this feature class. For example, in the image below, the red + represents raw locations determined by the IPS. These locations are snapped to the nearest line feature in the pathways feature table before being displayed. This provides a more consistent display of the blue dot as it moves across the map.
To create an indoors location data source by using an IPS
feature table, follow these steps:
-
Load the IPS-aware map. This can be a web map hosted as a portal item in ArcGIS Online or in ArcGIS Enterprise or as a map in a mobile map package (.mmpk) created with ArcGIS Pro.
-
Obtain the feature table, named "IPS_Positioning", from the map.
-
Find the pathways layer, named "Pathways", in the map's operational layers. Obtain the pathways feature table from the pathways layer.
-
Find the feature table, named "Levels", in the map's tables. This table is optional.
-
Create an
IndoorsLocationDataSource
using theIPS
and_Positioning Pathways
feature tables. Provide theLevels
feature tables, if it is present. -
Assign the
IndoorsLocationDataSource
to the map view'sLocationDisplay
. -
Enable the map view's location display. Device location will appear on the display as a blue dot and update as the user moves throughout the space.
You can read the positioning table and pathways dataset from the map and use them to create the IndoorsLocationDataSource
.
// View the "Show device location using indoor positioning" sample for a more detailed explanation of this code
// These functions loop through the map's tables and operational layers to find the given tables by name
FeatureTable* positioningTable = findPositioningTable("ips_positioning");
ArcGISFeatureTable* pathwaysTable = findPathwaysTable("Pathways");
// Create an indoors location data source from the tables, with an optional global id
IndoorsLocationDataSource* indoorsLDS = new IndoorsLocationDataSource(positioningTable, pathwaysTable, this);
Assign the IndoorsLocationDataSource
as the geoview's location display data source. Enable the location display to start receiving locations.
// Set the data source on the mapviews location display to the indoors location data source.
m_mapView->locationDisplay()->setDataSource(indoorsLDS);
// The slot which will receive location, heading, and status updates from the data source.
connect(m_mapView->locationDisplay(), &LocationDisplay::locationChanged, this, &DeviceLocation::locationChangedHandler);
// Start the location display on the map view.
m_mapView->locationDisplay()->start();
Handle location change
You can handle a status changed event so that the IndoorsLocationDataSource
is notified when the location data source starts, stops, or fails to start.
An IPS location populates additional properties with the current floor and the transmitter (beacon) count. When the floor changes, you can update the map to filter the display of features for the current floor. The floor value returned with the location is an integer that represents the vertical offset, where 0 is the ground floor. This value increases by one for each floor above the ground floor and decreases by one for each floor below.
// Test if the current floor is matches the desired "floor" key, if not change it.
if (locationProperties["floor"] != m_currentFloor)
{
m_currentFloor = locationProperties["floor"].toInt();
changeFloorDisplay();
}
// Get the key/value pairs additional meta-data and properties about the source of the location.
locationProperties = location.additionalSourceProperties();
// Set the "horizontalAccuracy" for the locaiton properties.
locationProperties["horizontalAccuracy"] = QVariant::fromValue(location.horizontalAccuracy());
// Call the locationPropertiesChanged signal.
emit locationPropertiesChanged();
In addition to getting the floor, you can get the position source, which will be BLE
(Bluetooth Low Energy) when using IPS and GNSS
(Global Navigation Satellite Systems) when using GPS. You can also get the count of transmitters (beacons) or satellites used to determine the location.
You can use a definition expression to filter layers in the map to only show features for the current floor. For efficiency, you should only filter features when the floor changes rather than with each location update. Depending on the schema for your floor-aware data, you may need to map the vertical offset value to a level ID in order to filter features by floor (level).
// Loop thru the operational layers in the map.
for (Layer* layer : *(m_map->operationalLayers()))
{
// Filter applicable layers to show features for the current floor (level).
if (layer->layerType() == LayerType::FeatureLayer && (layer->name() == "Details" || layer->name() == "Units" || layer->name() == "Levels"))
{
// Cast the layer to a feature layer.
FeatureLayer* featureLayer = static_cast<FeatureLayer*>(layer);
// Set the definition expression on the feature layer (restricts what is shown in the map).
featureLayer->setDefinitionExpression(QString{"VERTICAL_ORDER = %1"}.arg(m_currentFloor));
}
}
App permissions
If your app is using Bluetooth on the device to scan for beacon signals or GPS, make sure to add the appropriate permissions.
Android: Add these permissions to your Android
file.
android.permission.BLUETOOTH_ADMIN
android.permission.BLUETOOTH
android.permission.ACCESS_FINE_LOCATION
iOS: Add this key to your app's Info.plist
file.
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Bluetooth access is required for indoor positioning</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location services are required for GNSS positioning</string>