Hoe maak en vind ik ankers met behulp van Azure Spatial Anchors in Unity

Met Azure Spatial Anchors kunt u ankers delen tussen verschillende apparaten. Er worden meerdere ontwikkelomgevingen ondersteund. In dit artikel gaan we dieper in op het gebruik van de Azure Spatial Anchors SDK in Unity om:

  • een Azure Spatial Anchors-sessie correct in te stellen en te beheren.
  • eigenschappen op lokale ankers te maken en in te stellen.
  • gegevens naar de cloud te uploaden.
  • ruimtelijke ankers in de cloud te vinden en verwijderen.

Vereisten

Om deze zelfstudie te voltooien, moet u ervoor zorgen dat u:

Cross Platform

De sessie initialiseren

Het belangrijkste invoerpunt voor de SDK is de klasse die uw sessie weergeeft. Normaal gesproken declareert u een veld in de klasse waarmee uw weergave en de systeemeigen AR-sessie worden beheerd.

Meer informatie over de les CloudSpatialAnchorSession.

    CloudSpatialAnchorSession cloudSession;
    // In your view handler
    this.cloudSession = new CloudSpatialAnchorSession();

Verificatie instellen

Voor toegang tot de service moet u een accountsleutel, toegangstoken of Microsoft Entra-verificatietoken opgeven. U kunt hierover meer lezen op de conceptpagina Verificatie.

Accountsleutels

Accountsleutels zijn een referentie waarmee uw toepassing kan worden geverifieerd bij de service Azure Spatial Anchors. Het beoogde doel van accountsleutels is om snel aan de slag te kunnen. Met name tijdens de ontwikkelingsfase van de integratie van uw toepassing met Azure Spatial Anchors. Zo kunt u accountsleutels gebruiken door ze tijdens het ontwikkelen in uw clienttoepassingen in te sluiten. Naarmate u verdergaat met ontwikkelen, wordt het ten zeerste aanbevolen om over te stappen naar een verificatiemechanisme dat op productieniveau wordt ondersteund door Toegangstokens of Microsoft Entra-gebruikersverificatie. Als u een accountsleutel voor ontwikkeling wilt ophalen, gaat u in uw Azure Spatial Anchors-account en naar het tabblad Sleutels.

Meer informatie over de les SessionConfiguration.

    this.cloudSession.Configuration.AccountKey = @"MyAccountKey";

Toegangstokens

Toegangstokens zijn een meer robuuste methode om verificatie uit te voeren bij Azure Spatial Anchors. Met name wanneer u de toepassing voorbereidt voor een productie-implementatie. Samengevat: stel een back-endservice in waarmee uw clienttoepassing veilig kan worden geverifieerd. Uw back-endservice communiceert tijdens runtime met AAD en met de beveiligingstokenservice van Azure Spatial Anchors om een toegangstoken aan te vragen. Dit token wordt vervolgens afgeleverd aan de clienttoepassing en wordt in de SDK gebruikt om verificatie bij Azure Spatial Anchors uit te voeren.

    this.cloudSession.Configuration.AccessToken = @"MyAccessToken";

Als er geen toegangstoken is ingesteld, moet u de TokenRequired gebeurtenis afhandelen of de methode tokenRequired implementeren op het gemachtigde protocol.

U kunt de gebeurtenis synchroon afhandelen door de eigenschap voor de gebeurtenisargumenten in te stellen.

Meer informatie over de gemachtigde TokenRequiredDelegate.

    this.cloudSession.TokenRequired += (object sender, TokenRequiredEventArgs args) =>
    {
        args.AccessToken = @"MyAccessToken";
    };

Als u asynchroon werk in uw handler wilt uitvoeren, kunt u het instellen van het token uitstellen door een deferral-object aan te vragen en het vervolgens te voltooien, zoals in het volgende voorbeeld.

    this.cloudSession.TokenRequired += async (object sender, TokenRequiredEventArgs args) =>
    {
        var deferral = args.GetDeferral();
        string myToken = await MyGetTokenAsync();
        if (myToken != null) args.AccessToken = myToken;
        deferral.Complete();
    };

Microsoft Entra-verificatie

Met Azure Spatial Anchors kunnen toepassingen ook worden geverifieerd met Microsoft Entra ID-tokens (Active Directory). U kunt bijvoorbeeld Microsoft Entra-tokens gebruiken om te integreren met Azure Spatial Anchors. Als een Enterprise gebruikers onderhoudt in Microsoft Entra ID, kunt u een Microsoft Entra-token van een gebruiker opgeven in de Azure Spatial Anchors SDK. Hierdoor kunt u zich rechtstreeks verifiëren bij de Azure Spatial Anchors-service voor een account dat deel uitmaakt van dezelfde Microsoft Entra-tenant.

    this.cloudSession.Configuration.AuthenticationToken = @"MyAuthenticationToken";

Net als bij toegangstokens moet u, als een Microsoft Entra-token niet is ingesteld, de tokenRequired-gebeurtenis afhandelen of de methode tokenRequired implementeren in het gemachtigde protocol.

U kunt de gebeurtenis synchroon afhandelen door de eigenschap voor de gebeurtenisargumenten in te stellen.

    this.cloudSession.TokenRequired += (object sender, TokenRequiredEventArgs args) =>
    {
        args.AuthenticationToken = @"MyAuthenticationToken";
    };

Als u asynchroon werk in uw handler wilt uitvoeren, kunt u het instellen van het token uitstellen door een deferral-object aan te vragen en het vervolgens te voltooien, zoals in het volgende voorbeeld.

    this.cloudSession.TokenRequired += async (object sender, TokenRequiredEventArgs args) =>
    {
        var deferral = args.GetDeferral();
        string myToken = await MyGetTokenAsync();
        if (myToken != null) args.AuthenticationToken = myToken;
        deferral.Complete();
    };

De sessie instellen

Start() aanroepen om uw sessie in staat te stellen omgevingsgegevens te verwerken.

Als u gebeurtenissen wilt afhandelen die door uw sessie worden gegenereerd, koppelt u een gebeurtenis-handler.

Meer informatie over de methode Start.

#if UNITY_ANDROID || UNITY_IOS
    this.cloudSession.Session = aRSession.subsystem.nativePtr.GetPlatformPointer();
#elif UNITY_WSA || WINDOWS_UWP
    // No need to set a native session pointer for HoloLens.
#else
    throw new NotSupportedException("The platform is not supported.");
#endif

    this.cloudSession.Start();

De sessie voorzien van frames

De ruimtelijke-ankersessie werkt door de ruimte rond de gebruiker toe te wijzen. Zo kunt u bepalen waar de ankers zich moeten bevinden. Mobiele platformen (iOS en Android) vereisen een systeemeigen aanroep naar de camerafeed om frames van de AR-bibliotheek van uw platform te verkrijgen. Daarentegen wordt de omgeving voortdurend gescand door HoloLens, dus er is geen specifieke aanroep nodig, zoals bij mobiele platforms.

Meer informatie over de methode ProcessFrame.

#if UNITY_ANDROID || UNITY_IOS
    XRCameraFrame xRCameraFrame;
    if (aRCameraManager.subsystem.TryGetLatestFrame(cameraParams, out xRCameraFrame))
    {
        long latestFrameTimeStamp = xRCameraFrame.timestampNs;

        bool newFrameToProcess = latestFrameTimeStamp > lastFrameProcessedTimeStamp;

        if (newFrameToProcess)
        {
            session.ProcessFrame(xRCameraFrame.nativePtr.GetPlatformPointer());
            lastFrameProcessedTimeStamp = latestFrameTimeStamp;
        }
    }
#endif

De gebruiker feedback geven

U kunt code schrijven voor het verwerken van de actuele sessiegebeurtenis. Deze gebeurtenis wordt geactiveerd wanneer het begrip van uw omgeving door de sessie worden verbeterd. Hierdoor kunt u het volgende doen:

  • Klasse UserFeedback gebruiken om feedback te geven aan de gebruiker terwijl het apparaat beweegt en het begrip van de omgeving wordt bijgewerkt. Dit wilt doen
  • Bepaal op welk moment er voldoende getraceerde ruimtelijke gegevens zijn om ruimtelijke ankers te maken. U kunt dit vaststellen met ReadyForCreateProgress of RecommendedForCreateProgress. Als ReadyForCreateProgress meer is dan 1, zijn er voldoende gegevens om een ruimtelijk anker in de cloud op te slaan. Het is echter raadzaam te wachten tot RecommendedForCreateProgress groter is dan 1.

Meer informatie over de gemachtigde SessionUpdatedDelegate.

    this.cloudSession.SessionUpdated += (object sender, SessionUpdatedEventArgs args) =>
    {
        var status = args.Status;
        if (status.UserFeedback == SessionUserFeedback.None) return;
        this.feedback = $"Feedback: {Enum.GetName(typeof(SessionUserFeedback), status.UserFeedback)} -" +
            $" Recommend Create={status.RecommendedForCreateProgress: 0.#%}";
    };

Een ruimtelijk anker in de cloud maken

Als u een ruimtelijk anker in de Cloud wilt maken, maakt u eerst een anker in het AR-systeem van uw platform en maakt u vervolgens een equivalent in de cloud. U gebruikt de CreateAnchorAsync()-methode.

Meer informatie over de les CloudSpatialAnchor.

    // Create a local anchor, perhaps by hit-testing and spawning an object within the scene
    Vector3 hitPosition = new Vector3();
#if UNITY_ANDROID || UNITY_IOS
    Vector2 screenCenter = new Vector2(0.5f, 0.5f);
    List<ARRaycastHit> aRRaycastHits = new List<ARRaycastHit>();
    if(arRaycastManager.Raycast(screenCenter, aRRaycastHits) && aRRaycastHits.Count > 0)
    {
        ARRaycastHit hit = aRRaycastHits[0];
        hitPosition = hit.pose.position;
    }
#elif WINDOWS_UWP || UNITY_WSA
    RaycastHit hit;
    if (this.TryGazeHitTest(out hit))
    {
        hitPosition = hit.point;
    }
#endif

    Quaternion rotation = Quaternion.AngleAxis(0, Vector3.up);
    this.localAnchor = GameObject.Instantiate(/* some prefab */, hitPosition, rotation);
    this.localAnchor.AddComponent<CloudNativeAnchor>();

    // If the user is placing some application content in their environment,
    // you might show content at this anchor for a while, then save when
    // the user confirms placement.
    CloudNativeAnchor cloudNativeAnchor = this.localAnchor.GetComponent<CloudNativeAnchor>();
    if (cloudNativeAnchor.CloudAnchor == null) { await cloudNativeAnchor.NativeToCloud(); }  
    CloudSpatialAnchor cloudAnchor = cloudNativeAnchor.CloudAnchor;
    await this.cloudSession.CreateAnchorAsync(cloudAnchor);
    this.feedback = $"Created a cloud anchor with ID={cloudAnchor.Identifier}");

Zoals eerder beschreven, hebt u voldoende omgevingsgegevens nodig voor het maken van een nieuw ruimtelijk anker voor de cloud. Dit betekent dat ReadyForCreateProgress hoger dan 1 moet zijn, maar we raden u aan om te wachten tot RecommendedForCreateProgress hoger dan 1 is.

Meer informatie over de methode GetSessionStatusAsync.

    SessionStatus value = await this.cloudSession.GetSessionStatusAsync();
    if (value.RecommendedForCreateProgress < 1.0f) return;
    // Issue the creation request ...

Eigenschappen instellen

U kunt ervoor kiezen bepaalde eigenschappen toe te voegen bij het opslaan van ruimtelijke ankers in de cloud. Zoals het type object dat wordt opgeslagen of basiseigenschappen, bijvoorbeeld of het voor interactie moet worden ingeschakeld. Dit kan handig zijn bij detectie: u kunt het object direct voor de gebruiker weergeven, bijvoorbeeld een afbeeldingskader met lege inhoud. Vervolgens krijgt een andere downloadactie op de achtergrond aanvullende statusdetails, bijvoorbeeld de afbeelding die in het kader moet worden weergegeven.

Meer informatie over de eigenschap AppProperties.

    CloudSpatialAnchor cloudAnchor = new CloudSpatialAnchor() { LocalAnchor = localAnchor };
    cloudAnchor.AppProperties[@"model-type"] = @"frame";
    cloudAnchor.AppProperties[@"label"] = @"my latest picture";
    await this.cloudSession.CreateAnchorAsync(cloudAnchor);

Eigenschappen bijwerken

Als u de eigenschappen van een anker wilt bijwerken, gebruikt u methode UpdateAnchorProperties(). Als twee of meer apparaten de eigenschappen van hetzelfde anker op hetzelfde moment proberen bij te werken, wordt een model voor optimistische gelijktijdigheid gebruikt. Dit betekent dat de eerste schrijfbewerking wint. Bij alle andere schrijfbewerkingen wordt een gelijktijdigheidsfout weergeven: vernieuw de eigenschappen voordat u het opnieuw probeert.

Meer informatie over de methode UpdateAnchorPropertiesAsync.

    CloudSpatialAnchor anchor = /* locate your anchor */;
    anchor.AppProperties[@"last-user-access"] = @"just now";
    await this.cloudSession.UpdateAnchorPropertiesAsync(anchor);

U kunt de locatie van een anker niet bijwerken wanneer het is gemaakt voor de service. U moet een nieuw anker maken en het oude verwijderen om een nieuwe positie bij te houden.

Als u geen anker hoeft te lokaliseren om de eigenschappen ervan bij te werken, kunt u methode GetAnchorPropertiesAsync() gebruiken, waarmee een CloudSpatialAnchor-object met eigenschappen wordt geretourneerd.

Meer informatie over de methode GetAnchorPropertiesAsync.

    var anchor = await cloudSession.GetAnchorPropertiesAsync(@"anchorId");
    if (anchor != null)
    {
        anchor.AppProperties[@"last-user-access"] = @"just now";
        await this.cloudSession.UpdateAnchorPropertiesAsync(anchor);
    }

Vervaldatum instellen

Het is ook mogelijk uw anker zodanig te configureren dat deze op een bepaalde datum verloopt. Wanneer een anker verloopt, kan het niet meer worden gelokaliseerd of bijgewerkt. De vervaldatum kan alleen worden ingesteld wanneer het anker wordt gemaakt, voordat het in de cloud wordt opgeslagen. Het is niet mogelijk de vervaldatum daarna nog bij te werken. Als er geen verloopdatum is ingesteld tijdens het maken van het anker, verloopt het anker alleen wanneer het handmatig wordt verwijderd.

Meer informatie over de eigenschap Expiration.

    cloudAnchor.Expiration = DateTimeOffset.Now.AddDays(7);

Een ruimtelijk anker in de cloud lokaliseren

Een van de belangrijkste redenen om Azure Spatial Anchors te gebruiken, is dat u een eerder opgeslagen ruimtelijk anker in de cloud kunt lokaliseren. Hiervoor gebruiken we Watchers. U kunt slechts één Watcher tegelijk gebruiken; meerdere Watchers worden niet ondersteund. Een Watcher kan op verschillende manieren (ook wel 'Anchor Locate Strategies' genoemd) een ruimtelijk anker in de cloud vinden. Voor een watcher kunt u één strategie per keer gebruiken.

  • Lokaliseer ankers op id.
  • Lokaliseer ankers die zijn verbonden met een eerder gelokaliseerd anker. U vindt hier informatie over ankerrelaties.
  • Lokaliseer een anker met grove herlokalisatie.

Notitie

Telkens wanneer u een anker lokaliseert, probeert Azure Spatial Anchors de omgevingsgegevens te gebruiken die zijn verzameld om de visuele informatie op het anker te verbeteren. Als u problemen ondervindt bij het lokaliseren van een anker, kan het nuttig zijn om een anker te maken en deze vervolgens meerdere keren vanuit verschillende hoeken en lichtomstandigheden te lokaliseren.

Als u ruimtelijke ankers voor de cloud op id zoekt, kunt u de ruimtelijke anker-id van de cloud opslaan in de back-endservice van uw toepassing en toegankelijk maken voor alle apparaten die er goed bij kunnen worden geverifieerd. Zie zelfstudie: Spatial Anchors delen op verschillende apparaten voor een voorbeeld hiervan.

Instantieer een AnchorLocateCriteria-object, stel de id's in die u zoekt en roep de CreateWatcher-methode voor de sessie aan door uw AnchorLocateCriteria op te geven.

Meer informatie over de methode CreateWatcher.

    AnchorLocateCriteria criteria = new AnchorLocateCriteria();
    criteria.Identifiers = new string[] { @"id1", @"id2", @"id3" };
    this.cloudSession.CreateWatcher(criteria);

Nadat de watcher is gemaakt, wordt de AnchorLocated-gebeurtenis voor elk aangevraagd anker geactiveerd. Deze gebeurtenis wordt geactiveerd wanneer er een anker wordt gelokaliseerd of als het anker niet kan worden gelokaliseerd. Als deze situatie zich voordoet, wordt de reden aangegeven in de status. Nadat alle ankers voor een watcher zijn verwerkt, gevonden of niet gevonden, wordt de LocateAnchorsCompleted-gebeurtenis geactiveerd. Er geldt een limiet van 35 id's per watcher.

Meer informatie over de gemachtigde AnchorLocatedDelegate.

    this.cloudSession.AnchorLocated += (object sender, AnchorLocatedEventArgs args) =>
    {
        switch (args.Status)
        {
            case LocateAnchorStatus.Located:
                CloudSpatialAnchor foundAnchor = args.Anchor;
                // Go add your anchor to the scene...
                break;
            case LocateAnchorStatus.AlreadyTracked:
                // This anchor has already been reported and is being tracked
                break;
            case LocateAnchorStatus.NotLocatedAnchorDoesNotExist:
                // The anchor was deleted or never existed in the first place
                // Drop it, or show UI to ask user to anchor the content anew
                break;
            case LocateAnchorStatus.NotLocated:
                // The anchor hasn't been found given the location data
                // The user might in the wrong location, or maybe more data will help
                // Show UI to tell user to keep looking around
                break;
        }
    }

Ankers verwijderen

Het verwijderen van ankers wanneer deze niet meer wordt gebruikt, is een goede gewoonte om in uw ontwikkelingsproces en -procedures vroegtijdig op te nemen om uw Azure-resources te laten opschonen.

Meer informatie over de methode DeleteAnchorAsync.

    await this.cloudSession.DeleteAnchorAsync(cloudAnchor);
    // Perform any processing you may want when delete finishes

Anker verwijderen zonder te zoeken

Als u een anker niet kunt vinden, maar het nog steeds wilt verwijderen, kunt u de GetAnchorPropertiesAsync API gebruiken die een anchorId als invoer gebruikt om het CloudSpatialAnchor object op te halen. U kunt dit object DeleteAnchorAsync vervolgens doorgeven om het te verwijderen.

var anchor = await cloudSession.GetAnchorPropertiesAsync(@"anchorId");
await this.cloudSession.DeleteAnchorAsync(anchor);

De sessie onderbreken, opnieuw instellen of stoppen

Als u de sessie tijdelijk wilt stoppen, kunt u Stop() aanroepen. Als u dit doet, worden alle watchers en de omgevingsverwerking gestopt, zelfs als u ProcessFrame() aanroept. Vervolgens kunt u Start() aanroepen om de verwerking te hervatten. Bij het hervatten blijven de omgevingsgegevens die al in de sessie zijn vastgelegd, behouden.

Meer informatie over de methode Stop.

    this.cloudSession.Stop();

Als u de omgevingsgegevens die in uw sessie zijn vastgelegd opnieuw wilt instellen, kunt u Reset()aanroepen.

Meer informatie over de methode Reset.

    this.cloudSession.Reset();

Roep Dispose() aan om op de juiste manier op te schonen na een sessie.

Meer informatie over de methode Dispose.

    this.cloudSession.Dispose();

Volgende stappen

In deze handleiding hebt u geleerd hoe u ankers kunt maken en vinden met behulp van Azure Spatial Anchors SDK. Ga verder met de volgende handleiding voor meer informatie over ankerrelaties.