Skapa och hitta fästpunkter med Hjälp av Azure Spatial Anchors i Java

Med Azure Spatial Anchors kan du dela fästpunkter i världen mellan olika enheter. Den stöder flera olika utvecklingsmiljöer. I den här artikeln går vi in på hur du använder Azure Spatial Anchors SDK i Java för att:

  • Konfigurera och hantera en Azure Spatial Anchors-session korrekt.
  • Skapa och ange egenskaper för lokala fästpunkter.
  • Ladda upp dem till molnet.
  • Leta upp och ta bort molnbaserade fästpunkter.

Förutsättningar

För att slutföra den här guiden kontrollerar du att du har:

  • Läs igenom översikten över Azure Spatial Anchors.
  • En av snabbstarterna på 5 minuter har slutförts.
  • Grundläggande kunskaper om Java.
  • Grundläggande kunskaper om ARCore.

Cross Platform

Initiera sessionen

Huvudinmatningspunkten för SDK:t är klassen som representerar din session. Vanligtvis deklarerar du ett fält i klassen som hanterar din vy och den interna AR-sessionen.

Läs mer om klassen CloudSpatialAnchorSession .

    private CloudSpatialAnchorSession mCloudSession;
    // In your view handler
    mCloudSession = new CloudSpatialAnchorSession();

Konfigurera autentisering

För att få åtkomst till tjänsten måste du ange en kontonyckel, åtkomsttoken eller Microsoft Entra-autentiseringstoken. Du kan också läsa mer om detta på sidan Autentiseringskoncept.

Kontonycklar

Kontonycklar är en autentiseringsuppgift som gör att ditt program kan autentisera med Azure Spatial Anchors-tjänsten. Syftet med kontonycklar är att hjälpa dig att komma igång snabbt. Särskilt under utvecklingsfasen av programmets integrering med Azure Spatial Anchors. Därför kan du använda kontonycklar genom att bädda in dem i dina klientprogram under utvecklingen. När du går vidare efter utvecklingen rekommenderar vi starkt att du går över till en autentiseringsmekanism som är på produktionsnivå, som stöds av åtkomsttoken eller Microsoft Entra-användarautentisering. Om du vill hämta en kontonyckel för utveckling går du till ditt Azure Spatial Anchors-konto och går till fliken Nycklar.

Läs mer om klassen SessionConfiguration .

    mCloudSession.getConfiguration().setAccountKey("MyAccountKey");

Åtkomsttoken

Åtkomsttoken är en mer robust metod för att autentisera med Azure Spatial Anchors. Särskilt när du förbereder programmet för en produktionsdistribution. Sammanfattningen av den här metoden är att konfigurera en serverdelstjänst som klientprogrammet kan autentisera säkert med. Dina serverdelstjänstgränssnitt med AAD vid körning och med Azure Spatial Anchors Secure Token Service för att begära en åtkomsttoken. Den här token levereras sedan till klientprogrammet och används i SDK för att autentisera med Azure Spatial Anchors.

    mCloudSession.getConfiguration().setAccessToken("MyAccessToken");

Om en åtkomsttoken inte har angetts måste du hantera TokenRequired händelsen eller implementera tokenRequired metoden i ombudsprotokollet.

Du kan hantera händelsen synkront genom att ange egenskapen på händelseargumenten.

Läs mer om gränssnittet TokenRequiredListener .

    mCloudSession.addTokenRequiredListener(args -> {
        args.setAccessToken("MyAccessToken");
    });

Om du behöver köra asynkront arbete i hanteraren kan du skjuta upp inställningen av token genom att begära ett deferral objekt och sedan slutföra det, som i följande exempel.

    mCloudSession.addTokenRequiredListener(args -> {
        CloudSpatialAnchorSessionDeferral deferral = args.getDeferral();
        MyGetTokenAsync(myToken -> {
            if (myToken != null) args.setAccessToken(myToken);
            deferral.complete();
        });
    });

Microsoft Entra-autentisering

Azure Spatial Anchors gör det också möjligt för program att autentisera med användartoken för Microsoft Entra-ID (Active Directory). Du kan till exempel använda Microsoft Entra-token för att integrera med Azure Spatial Anchors. Om ett företag underhåller användare i Microsoft Entra-ID kan du ange en Microsoft Entra-token för användare i Azure Spatial Anchors SDK. På så sätt kan du autentisera direkt till Azure Spatial Anchors-tjänsten för ett konto som ingår i samma Microsoft Entra-klientorganisation.

    mCloudSession.getConfiguration().setAuthenticationToken("MyAuthenticationToken");

Precis som med åtkomsttoken måste du hantera tokenRequired-händelsen om en Microsoft Entra-token inte har angetts eller implementera metoden tokenRequired i ombudsprotokollet.

Du kan hantera händelsen synkront genom att ange egenskapen på händelseargumenten.

    mCloudSession.addTokenRequiredListener(args -> {
        args.setAuthenticationToken("MyAuthenticationToken");
    });

Om du behöver köra asynkront arbete i hanteraren kan du skjuta upp inställningen av token genom att begära ett deferral objekt och sedan slutföra det, som i följande exempel.

    mCloudSession.addTokenRequiredListener(args -> {
        CloudSpatialAnchorSessionDeferral deferral = args.getDeferral();
        MyGetTokenAsync(myToken -> {
            if (myToken != null) args.setAuthenticationToken(myToken);
            deferral.complete();
        });
    });

Konfigurera sessionen

Anropa Start() för att aktivera sessionen för att bearbeta miljödata.

Om du vill hantera händelser som genererats av sessionen bifogar du en händelsehanterare.

    mCloudSession.setSession(mSession);
    mCloudSession.start();

Ange ramar till sessionen

Den rumsliga fästpunktssessionen fungerar genom att mappa utrymmet runt användaren. Det hjälper dig att avgöra var fästpunkter finns. Mobila plattformar (iOS och Android) kräver ett internt anrop till kameraflödet för att hämta ramar från plattformens AR-bibliotek. HoloLens genomsöker däremot hela tiden miljön, så det finns inget behov av ett specifikt samtal som på mobila plattformar.

    mCloudSession.processFrame(mSession.update());

Ge feedback till användaren

Du kan skriva kod för att hantera sessionens uppdaterade händelse. Den här händelsen utlöses varje gång sessionen förbättrar sin förståelse för din omgivning. Om du gör det kan du:

  • UserFeedback Använd klassen för att ge feedback till användaren när enheten flyttas och sessionen uppdaterar sin miljötolkning. Gör
  • Fastställ vid vilken tidpunkt det finns tillräckligt med spårade rumsliga data för att skapa spatiala fästpunkter. Du avgör detta med antingen ReadyForCreateProgress eller RecommendedForCreateProgress. När ReadyForCreateProgress är över 1 har vi tillräckligt med data för att spara ett moln spatialt fästpunkt, men vi rekommenderar att du väntar tills RecommendedForCreateProgress är över 1 för att göra det.

Läs mer om gränssnittet SessionUpdatedListener .

    mCloudSession.addSessionUpdatedListener(args -> {
        auto status = args->Status();
        if (status->UserFeedback() == SessionUserFeedback::None) return;
        NumberFormat percentFormat = NumberFormat.getPercentInstance();
        percentFormat.setMaximumFractionDigits(1);
        mFeedback = String.format("Feedback: %s - Recommend Create=%s",
            FeedbackToString(status.getUserFeedback()),
            percentFormat.format(status.getRecommendedForCreateProgress()));
    });

Skapa ett rumsligt molnfästpunkt

Om du vill skapa ett rumsligt molnankare skapar du först en fästpunkt i plattformens AR-system och skapar sedan en molnmotsvarighet. Du använder CreateAnchorAsync() metoden .

Läs mer om klassen CloudSpatialAnchor .

    // Create a local anchor, perhaps by hit-testing and creating an ARAnchor
    Anchor localAnchor = null;
    List<HitResult> hitResults = mSession.update().hitTest(0.5f, 0.5f);
    for (HitResult hit : hitResults) {
        Trackable trackable = hit.getTrackable();
        if (trackable instanceof Plane) {
            if (((Plane) trackable).isPoseInPolygon(hit.getHitPose())) {
                localAnchor = hit.createAnchor();
                break;
            }
        }
    }

    // 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.
    CloudSpatialAnchor cloudAnchor = new CloudSpatialAnchor();
    cloudAnchor.setLocalAnchor(localAnchor);
    Future createAnchorFuture = mCloudSession.createAnchorAsync(cloudAnchor);
    CheckForCompletion(createAnchorFuture, cloudAnchor);

    // ...

    private void CheckForCompletion(Future createAnchorFuture, CloudSpatialAnchor cloudAnchor) {
        new android.os.Handler().postDelayed(() -> {
            if (createAnchorFuture.isDone()) {
                try {
                    createAnchorFuture.get();
                    mFeedback = String.format("Created a cloud anchor with ID=%s", cloudAnchor.getIdentifier());
                }
                catch(InterruptedException e) {
                    mFeedback = String.format("Save Failed:%s", e.getMessage());
                }
                catch(ExecutionException e) {
                    mFeedback = String.format("Save Failed:%s", e.getMessage());
                }
            }
            else {
                CheckForCompletion(createAnchorFuture, cloudAnchor);
            }
        }, 500);
    }

Som vi beskrev tidigare behöver du tillräckligt med miljödata som samlas in innan du försöker skapa ett nytt rumsligt molnankare. Det innebär ReadyForCreateProgress att måste vara över 1, men vi rekommenderar att du väntar tills RecommendedForCreateProgress är över 1 för att göra det.

    Future<SessionStatus> sessionStatusFuture = mCloudSession.getSessionStatusAsync();
    CheckForCompletion(sessionStatusFuture);

    // ...

    private void CheckForCompletion(Future<SessionStatus> sessionStatusFuture) {
        new android.os.Handler().postDelayed(() -> {
            if (sessionStatusFuture.isDone()) {
                try {
                    SessionStatus value = sessionStatusFuture.get();
                    if (value.getRecommendedForCreateProgress() < 1.0f) return;
                    // Issue the creation request...
                }
                catch(InterruptedException e) {
                    mFeedback = String.format("Session status error:%s", e.getMessage());
                }
                catch(ExecutionException e) {
                    mFeedback = String.format("Session status error:%s", e.getMessage());
                }
            }
            else {
                CheckForCompletion(sessionStatusFuture);
            }
        }, 500);
    }

Ange egenskaper

Du kan välja att lägga till vissa egenskaper när du sparar dina molnbaserade fästpunkter. Som vilken typ av objekt som sparas eller grundläggande egenskaper som om det ska aktiveras för interaktion. Det kan vara användbart vid identifiering: du kan omedelbart återge objektet för användaren, till exempel en bildram med tomt innehåll. Sedan får en annan nedladdning i bakgrunden ytterligare tillståndsinformation, till exempel den bild som ska visas i ramen.

    CloudSpatialAnchor cloudAnchor = new CloudSpatialAnchor();
    cloudAnchor.setLocalAnchor(localAnchor);
    Map<String,String> properties = cloudAnchor.getAppProperties();
    properties.put("model-type", "frame");
    properties.put("label", "my latest picture");
    Future createAnchorFuture = mCloudSession.createAnchorAsync(cloudAnchor);
    // ...

Uppdatera egenskaper

Om du vill uppdatera egenskaperna för en fästpunkt använder UpdateAnchorProperties() du metoden. Om två eller flera enheter försöker uppdatera egenskaper för samma fästpunkt samtidigt använder vi en optimistisk samtidighetsmodell. Vilket innebär att den första skrivningen kommer att vinna. Alla andra skrivningar får felet "Samtidighet": en uppdatering av egenskaperna skulle behövas innan du försöker igen.

    CloudSpatialAnchor anchor = /* locate your anchor */;
    anchor.getAppProperties().put("last-user-access", "just now");
    Future updateAnchorPropertiesFuture = mCloudSession.updateAnchorPropertiesAsync(anchor);
    CheckForCompletion(updateAnchorPropertiesFuture);

    // ...

    private void CheckForCompletion(Future updateAnchorPropertiesFuture) {
        new android.os.Handler().postDelayed(() -> {
            if (updateAnchorPropertiesFuture.isDone()) {
                try {
                    updateAnchorPropertiesFuture.get();
                }
                catch(InterruptedException e) {
                    mFeedback = String.format("Updating Properties Failed:%s", e.getMessage());
                }
                catch(ExecutionException e) {
                    mFeedback = String.format("Updating Properties Failed:%s", e.getMessage());
                }
            }
            else {
                CheckForCompletion1(updateAnchorPropertiesFuture);
            }
        }, 500);
    }

Du kan inte uppdatera platsen för en fästpunkt när den har skapats i tjänsten – du måste skapa ett nytt fästpunkt och ta bort den gamla för att spåra en ny position.

Om du inte behöver hitta ett fästpunkt för att uppdatera dess egenskaper kan du använda GetAnchorPropertiesAsync() metoden som returnerar ett CloudSpatialAnchor objekt med egenskaper.

    Future<CloudSpatialAnchor> getAnchorPropertiesFuture = mCloudSession.getAnchorPropertiesAsync("anchorId");
    CheckForCompletion(getAnchorPropertiesFuture);

    // ...

    private void CheckForCompletion(Future<CloudSpatialAnchor> getAnchorPropertiesFuture) {
        new android.os.Handler().postDelayed(() -> {
            if (getAnchorPropertiesFuture.isDone()) {
                try {
                    CloudSpatialAnchor anchor = getAnchorPropertiesFuture.get();
                    if (anchor != null) {
                        anchor.getAppProperties().put("last-user-access", "just now");
                        Future updateAnchorPropertiesFuture = mCloudSession.updateAnchorPropertiesAsync(anchor);
                        // ...
                    }
                } catch (InterruptedException e) {
                    mFeedback = String.format("Getting Properties Failed:%s", e.getMessage());
                } catch (ExecutionException e) {
                    mFeedback = String.format("Getting Properties Failed:%s", e.getMessage());
                }
            } else {
                CheckForCompletion(getAnchorPropertiesFuture);
            }
        }, 500);
    }

Ange förfallotid

Det går också att konfigurera fästpunkten så att den upphör att gälla automatiskt vid ett visst datum i framtiden. När en fästpunkt upphör att gälla kommer den inte längre att finnas eller uppdateras. Förfallodatum kan bara anges när fästpunkten skapas innan den sparas i molnet. Det går inte att uppdatera förfallodatum efteråt. Om ingen förfallotid anges när fästpunkten skapas upphör fästpunkten endast att gälla när den tas bort manuellt.

    Date now = new Date();
    Calendar cal = Calendar.getInstance();
    cal.setTime(now);
    cal.add(Calendar.DATE, 7);
    Date oneWeekFromNow = cal.getTime();
    cloudAnchor.setExpiration(oneWeekFromNow);

Leta upp ett rumsligt molnfästpunkt

Att kunna hitta en tidigare sparad molnlokal fästpunkt är en av de främsta orsakerna till att använda Azure Spatial Anchors. För detta använder vi "Watchers". Du kan bara använda en Watcher i taget. flera bevakare stöds inte. Det finns flera olika sätt (kallas även Anchor Locate Strategies) en Watcher kan hitta en moln spatial fästpunkt. Du kan använda en strategi för en bevakare i taget.

  • Leta upp fästpunkter efter identifierare.
  • Leta upp fästpunkter som är anslutna till en tidigare fästpunkt. Du kan lära dig mer om ankarrelationer här.
  • Leta upp fästpunkt med hjälp av omlokalisering av grova objekt.

Kommentar

Varje gång du hittar en fästpunkt försöker Azure Spatial Anchors använda de miljödata som samlas in för att utöka den visuella informationen i fästpunkten. Om du har problem med att hitta ett fästpunkt kan det vara användbart att skapa ett fästpunkt och sedan hitta det flera gånger från olika vinklar och ljusförhållanden.

Om du letar upp molnbaserade fästpunkter efter identifierare kan du lagra molnbaserad fästpunktsidentifierare i programmets serverdelstjänst och göra den tillgänglig för alla enheter som kan autentisera den korrekt. Ett exempel på detta finns i Självstudie: Dela spatiala fästpunkter mellan enheter.

Instansiera ett AnchorLocateCriteria objekt, ange de identifierare som du letar efter och anropa CreateWatcher metoden i sessionen genom att ange din AnchorLocateCriteria.

    AnchorLocateCriteria criteria = new AnchorLocateCriteria();
    criteria.setIdentifiers(new String[] { "id1", "id2", "id3" });
    mCloudSession.createWatcher(criteria);

När din bevakare har skapats utlöses AnchorLocated händelsen för varje ankarpunkt som begärs. Den här händelsen utlöses när en fästpunkt finns eller om fästpunkten inte kan placeras. Om den här situationen inträffar anges orsaken i statusen. När alla fästpunkter för en bevakare har bearbetats, hittats eller inte hittats utlöses LocateAnchorsCompleted händelsen. Det finns en gräns på 35 identifierare per bevakare.

Läs mer om gränssnittet AnchorLocatedListener .

    mCloudSession.addAnchorLocatedListener(args -> {
        switch (args.getStatus()) {
            case Located:
                CloudSpatialAnchor foundAnchor = args.getAnchor();
                // Go add your anchor to the scene...
                break;
            case AlreadyTracked:
                // This anchor has already been reported and is being tracked
                break;
            case 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 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;
        }
    });

Ta bort fästpunkter

Att ta bort fästpunkter när de inte längre används är en bra idé att ta med tidigt i utvecklingsprocessen och metoderna för att hålla dina Azure-resurser rensade.

    Future deleteAnchorFuture = mCloudSession.deleteAnchorAsync(cloudAnchor);
    // Perform any processing you may want when delete finishes (deleteAnchorFuture is done)

Pausa, återställa eller stoppa sessionen

Om du vill stoppa sessionen tillfälligt kan du anropa Stop(). Om du gör det stoppas alla bevakare och miljöbearbetning, även om du anropar ProcessFrame(). Du kan sedan anropa Start() för att återuppta bearbetningen. När du återupptar underhålls miljödata som redan har samlats in i sessionen.

    mCloudSession.stop();

Om du vill återställa miljödata som har samlats in i sessionen kan du anropa Reset().

    mCloudSession.reset();

Om du vill rensa korrekt efter en session anropar close()du .

    mCloudSession.close();

Nästa steg

I den här guiden har du lärt dig hur du skapar och hittar fästpunkter med hjälp av Azure Spatial Anchors SDK. Om du vill veta mer om ankarrelationer fortsätter du till nästa guide.