Repository navigation
Geospatial API
ARCore's Geospatial API gives much more accurate placement than GPS and compass alone. The library uses it automatically when it's enabled and working.
- An ARCore-supported phone that supports Geospatial mode. Check with
session.isGeospatialModeSupported(Config.GeospatialMode.ENABLED). - Fine location permission, granted before the session is configured.
- Internet access, which the library's manifest already declares.
- Google Play services location, which the library already depends on.
- An API key or keyless authorisation from Google Cloud.
Follow Google's guide to enable the Geospatial API. It walks through creating a Google Cloud project, enabling the ARCore API and choosing between an API key and keyless authorisation.
With an API key, add it to your manifest:
<meta-data
android:name="com.google.android.ar.API_KEY"
android:value="YOUR_API_KEY" />The example app reads the key from arcore.apiKey in local.properties, so it stays out of source control.
Set the mode before configuring the session:
Config config = session.getConfig();
if (session.isGeospatialModeSupported(Config.GeospatialMode.ENABLED)) {
config.setGeospatialMode(Config.GeospatialMode.ENABLED);
}
session.configure(config);With Sceneform's ArFragment, do the same in its session configuration listener:
arFragment.setOnSessionConfigurationListener((session, config) -> {
if (session.isGeospatialModeSupported(Config.GeospatialMode.ENABLED)) {
config.setGeospatialMode(Config.GeospatialMode.ENABLED);
}
});Every frame, GeoTracker checks session.getEarth(). When the Earth is tracking and its horizontal accuracy is 15 metres or better, the tracker uses Geospatial poses and stops using GPS and compass. It discards its earlier GPS and compass estimates at that point, because the Geospatial ones are much better.
If Geospatial tracking is lost for more than three seconds, the tracker goes back to GPS and compass and keeps the Geospatial estimates until newer samples replace them.
stateDiagram-v2
state "Waiting for location and heading" as waiting
state "GPS and compass" as gps
state "Geospatial" as geo
[*] --> waiting: start()
waiting --> gps: GPS fix and compass heading recorded
waiting --> geo: Earth tracking, accuracy 15 m or better
gps --> geo: Earth tracking, accuracy 15 m or better.<br/>Earlier estimates are discarded.
geo --> gps: No usable Geospatial pose for 3 seconds.<br/>Geospatial estimates are kept.
GeoTracker.getSource() returns GEOSPATIAL or GPS_AND_COMPASS so you can show which is in use. getEarthState() returns ARCore's Earth.EarthState, which explains failures such as ERROR_NOT_AUTHORIZED.
To turn Geospatial off without changing the session, call tracker.setUseGeospatial(false).
Geospatial poses include altitude, so with the Geospatial API you can give a marker a real altitude:
GeoCoordinate.of(51.50073, -0.12463, 96.0) // metres above the WGS84 ellipsoidWGS84 ellipsoid height is not height above sea level; the two differ by up to about 100 metres depending on where you are. If you have heights above sea level, convert them first.