# Localizing and Tracking Anchors with VPS Source: https://www.nianticspatial.com/docs/nsdk/how-to/vps/tracking_anchors_swift/ Anchors are persistent spatial reference points that can be tracked across sessions and devices. The `Vps2Session` is responsible for managing these anchors and correlating them with their real-world geographic locations. Anchors persist individual points within a place you have already localized to. To localize to a Site itself, call `localize(siteId:)` -- see [Place virtual content with VPS2](https://www.nianticspatial.com/docs/nsdk/how-to/vps2/placing_virtual_content/). ## **Creating** anchors The `createAnchor(at:)` method creates a persistent anchor relative to the Site you are currently localized to, so you must localize to a Site first. Creating an anchor returns its unique `anchorId` string. ```swift let anchorPose = simd_float4x4(/* your transformation matrix */) do { let anchorId = try vps2Session.createAnchor(at: anchorPose) } catch { print("Failed to create anchor: \(error)") } ``` *The transformation matrix here can be assigned to any AR Content you'd want to place.* ## **Getting** anchor payloads The payload encodes the data needed to resolve an anchor across multiple devices or sessions. It is a string blob that can be shared or stored, is only available after the anchor's Site has been tracked, and is obtained from the `anchorPayload(anchorId:)` method. ```swift if let payloadState = vps2Session.anchorPayload(anchorId: anchorId) { switch payloadState { case .inProgress: print("Anchor payload is being generated...") case .success(let payload): // Payload is available - base64-encoded string saveAnchorPayload(payload, for: anchorId) default: print("Unknown error, default result hit") } } else { // No anchor with the given ID was found print("Anchor not found") } ``` The `anchorPayload(anchorId:)` returns: An \``NSDKAsyncState`\` representing the state of the anchor payload request:\ .`inProgress(nil)`: The anchor is not yet tracked, so the payload is not yet available.\ .`success(value)`: The request completed successfully. Contains the base64-encoded payload.\ `nil`: No anchor with id \`anchorId\` was found. ## **Tracking** existing anchors To bring back an anchor you saved earlier, or one shared by another device, pass its payload to `trackAnchor(payload:)`. Tracking also depends on localizing to the anchor's Site: the call is accepted at any time, but the anchor stays untracked until the session localizes to the Site it belongs to. ```swift do { let anchorId = try vps2Session.trackAnchor(payload: anchorPayload) } catch { print("Failed to track anchor: \(error)") } ``` The `trackAnchor(payload:)` returns the unique identifier of the anchor encoded in the payload once tracking has started. Note that successfully getting the id does not mean the anchor is being tracked yet, and for that we need to call the update function. ## **Updating** anchors After tracking an anchor, you'll need to explicitly poll for updates to get the anchor's state and latest pose and make corrections to any related AR content: ```swift // Poll for anchor updates every frame in your update loop if let update = vps2Session.anchorUpdate(anchorId: anchorId) { switch update.trackingState { case .tracked: // Localized and succesfully tracking the anchor. case .notTracked: // Handle untracked state (e.g., hide AR content) case .limited: // Tracking is limited or degraded default: //Default error message, example: "Unknown error, default result hit" } } ``` *The `VpsAnchorUpdate` object contains a lot of useful information, see the api reference for more information.* ## **Removing** anchors Once removed, the anchor will no longer receive updates or consume processing resources. ```swift if vps2Session.removeAnchor(withId: anchorId) { // if you are keeping local anchor references you'll need to handle those } else { // Failed to remove anchor (may not exist) } ``` This returns true if the anchor was removed, false if otherwise. Keep in mind that you'll still need to clear content associated with the anchor.\ *Note that this call uses the anchorId and not the payload.* # VPS Workflow: A typical VPS workflow involves the following sequence of steps: 1. **Initialization and Setup** - Initialize and set up your `ardkSession`. - **Note:** Ensure GPS data is included within the `ArdkFrameData`. 2. **Session Configuration and Start** - Configure and start the `vps2Session`. 3. **Anchor Management** - **Load and Get Payloads:** - *(Optional)* Load anchor payload(s) saved from previous sessions. - **Start Tracking:** Begin the anchor tracking process. - **Update and Maintain:** - Periodically call `anchorUpdate` to check for state or position changes in the anchors. - Handle any detected changes. - **Cleanup and Save:** - Remove any anchors that are no longer needed. - *(Optional)* Save any anchor payloads you want to be loaded in a subsequent session. 4. **Finalization** - End the session and clear all related content.