# Geolocate with VPS2 Source: https://www.nianticspatial.com/docs/nsdk/how-to/vps2/getting_vps2_geoposition/ Use VPS2 device geolocation to read the device's current geographic position and heading. For map-relative AR placement, localize to a Site or nearby coordinate and use the localized asset's tracking data, which gives the pose of the asset's origin in AR space (and, for georeferenced assets, the geolocation of that origin). ## Prerequisites This guide assumes that you have already completed: - [Get started with VPS2](https://www.nianticspatial.com/docs/nsdk/how-to/vps2/adding_vps2/) ## Get a precise geolocation Starting VPS2 on its own gives only a `coarse` geolocation, from local sensor fusion and, if enabled, universal localization. VPS2 never localizes to a VPS map by itself: **VPS Map Localization Enabled** only allows VPS map requests. For a `precise`, more accurate geolocation, also localize to nearby Sites with the device's current position, or to a specific Site by its ID: ### Platform: unity ```csharp if (vps2Manager.TryGetDeviceGeolocation(out var geolocation, HeadingMode.CameraDirection) && geolocation.TrackingState != Vps2TrackingState.Unavailable) { // Localize to every Site within the default radius (100 m) of the device. vps2Manager.TryLocalize(geolocation.Geolocation.Latitude, geolocation.Geolocation.Longitude); } ``` ### Platform: swift ```swift if let geolocation = vps2Session.deviceGeolocation(headingMode: .cameraDirection) { // Localize to every Site within the default radius (100 m) of the device. try vps2Session.localize(latitude: geolocation.geolocationData.latitude, longitude: geolocation.geolocationData.longitude) } ``` ### Platform: kotlin ```kotlin val geolocation = try { vps2Session.getDeviceGeolocation(HeadingMode.CAMERA_DIRECTION) } catch (_: NsdkInvalidOperationStatusException) { null // VPS2 tracking is unavailable. } // Localize to every Site within the default radius (100 m) of the device. geolocation?.let { vps2Session.localize(it.latitude, it.longitude) } ``` Once the device localizes to a Site's VPS map, the VPS2 tracking state becomes `precise` and the same geolocation calls return the improved position. Away from mapped Sites, the geolocation stays `coarse`. See [Tracking state](#tracking-state) below, and [Get started with VPS2](https://www.nianticspatial.com/docs/nsdk/how-to/vps2/adding_vps2/) for both `localize` calls. ## Device geolocation Retrieve the device's current geographic coordinates independently of any localized asset. The heading mode parameter controls how heading is computed: - Camera Direction: Heading from the camera's forward axis. Best when the device is held upright in portrait or landscape orientation. - Device Top: Heading from the top edge of the screen. Best when the device is face-up or for compass-style widgets. ### Platform: unity ```csharp if (vps2Manager.TryGetDeviceGeolocation(out var geolocation, HeadingMode.CameraDirection) && geolocation.TrackingState != Vps2TrackingState.Unavailable) { var latitude = geolocation.Geolocation.Latitude; var longitude = geolocation.Geolocation.Longitude; var altitude = geolocation.Geolocation.Altitude; var heading = geolocation.Geolocation.Heading; var horizontalAccuracy = geolocation.HorizontalAccuracy; var verticalAccuracy = geolocation.VerticalAccuracy; var headingAccuracy = geolocation.HeadingAccuracy; } ``` ### Platform: swift ```swift if let geolocation = vps2Session.deviceGeolocation(headingMode: .cameraDirection) { let latitude = geolocation.geolocationData.latitude let longitude = geolocation.geolocationData.longitude let altitude = geolocation.geolocationData.altitude let heading = geolocation.geolocationData.heading let horizontalAccuracy = geolocation.horizontalAccuracyMetres let verticalAccuracy = geolocation.verticalAccuracyMetres let rotationAccuracy = geolocation.rotationAccuracyDeg } ``` ### Platform: kotlin ```kotlin import com.nianticspatial.nsdk.NsdkInvalidOperationStatusException val geolocation = try { vps2Session.getDeviceGeolocation(HeadingMode.CAMERA_DIRECTION) } catch (_: NsdkInvalidOperationStatusException) { null // VPS2 tracking is unavailable. } geolocation?.let { geo -> val latitude = geo.latitude val longitude = geo.longitude val altitude = geo.altitude val heading = geo.heading val horizontalAccuracy = geo.horizontalAccuracyMetres val verticalAccuracy = geo.verticalAccuracyMetres val rotationAccuracy = geo.rotationAccuracyDeg } ``` ### Tracking state VPS2 reports the VPS2 tracking state -- a broad quality category for how well the device knows where it is in the world -- with three values: - **`unavailable`** -- VPS2 has no usable geoposition, either not yet or no longer, for example after losing GPS with no VPS map correction. The code above handles this case: ### Platform: unity`TryGetDeviceGeolocation` reports it as `Vps2TrackingState.Unavailable`### Platform: swift`deviceGeolocation()` returns `nil`### Platform: kotlin`getDeviceGeolocation()` throws `NsdkInvalidOperationStatusException`. - **`coarse`** -- An approximate global geoposition from local sensor fusion of GPS, AR tracking, and the compass when available, improved by universal localization when it is enabled. Good for large-scale alignment, but not for precise placement. This is the highest state available away from mapped Sites. - **`precise`** -- A high-accuracy geoposition, reached only after localizing to a Site's VPS map, and only as accurate as that map's [georeference](https://www.nianticspatial.com/docs/nsdk/features/vps2/#geo-alignment-and-absolute-accuracy). Universal localization alone never reaches this state. The state falls back to `coarse` or `unavailable` if the device loses its connection to that map, for example when AR tracking resets, so keep checking it. Wait for it when your content needs accurate placement from geographic coordinates. The state is a broad category, not a measurement -- use the accuracy values for numeric margins of error. Also, it describes the *device's* geoposition, which is separate from whether a localized asset is tracked for content placement; for that distinction and the full reference, see [Tracking states](https://www.nianticspatial.com/docs/nsdk/features/vps2/#tracking-states). ### Accuracy Each estimate includes accuracy values that represent margin-of-error estimates. Rely on these rather than assuming centimeter-level global alignment. Accuracy may vary across conversions performed with the same localization when using different input poses or locations. - **Horizontal accuracy** (meters) - **Vertical accuracy** (meters) - **Heading / rotation accuracy** (degrees) ## Use a localized asset for AR placement Calling `localize` starts a request; it does not itself provide a pose. After VPS2 reports a localized asset, read that asset's tracking data and render content only while the data is available. See [Place virtual content with VPS2](https://www.nianticspatial.com/docs/nsdk/how-to/vps2/placing_virtual_content/) for the platform-specific placement pattern. > **Note:** > > Use device geolocation for the device's latitude, longitude, altitude, and heading. Asset tracking data describes the asset's origin, not the device: its pose places the asset's origin in AR space, and its geolocation (present only for georeferenced assets) is the geographic position of that origin.