Jak tworzyć i lokalizować kotwice przy użyciu usługi Azure Spatial Anchors w języku Java

Usługa Azure Spatial Anchors umożliwia udostępnianie kotwic na całym świecie między różnymi urządzeniami. Obsługuje kilka różnych środowisk programistycznych. W tym artykule dowiesz się, jak używać zestawu AZURE Spatial Anchors SDK w języku Java w celu:

  • Poprawnie skonfiguruj sesję usługi Azure Spatial Anchors i zarządzaj nią.
  • Tworzenie i ustawianie właściwości na lokalnych kotwicach.
  • Przekaż je do chmury.
  • Lokalizowanie i usuwanie kotwic przestrzennych w chmurze.

Wymagania wstępne

Aby ukończyć ten przewodnik, upewnij się, że masz następujące elementy:

  • Zapoznaj się z omówieniem usługi Azure Spatial Anchors.
  • Ukończono jeden z 5-minutowych przewodników Szybki start.
  • Podstawowa wiedza na temat języka Java.
  • Podstawowa wiedza na temat arcore.

Cross Platform

Inicjowanie sesji

Głównym punktem wejścia zestawu SDK jest klasa reprezentująca sesję. Zazwyczaj należy zadeklarować pole w klasie, która zarządza widokiem i natywną sesją ar.

Dowiedz się więcej o klasie CloudSpatialAnchorSession .

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

Konfigurowanie uwierzytelniania

Aby uzyskać dostęp do usługi, musisz podać klucz konta, token dostępu lub token uwierzytelniania entra firmy Microsoft. Więcej informacji na ten temat można również uzyskać na stronie Pojęcia uwierzytelniania.

Klucze kont

Klucze konta to poświadczenia, które umożliwiają aplikacji uwierzytelnianie za pomocą usługi Azure Spatial Anchors. Celem kluczy kont jest ułatwienie szybkiego rozpoczęcia pracy. Szczególnie w fazie opracowywania integracji aplikacji z usługą Azure Spatial Anchors. W związku z tym możesz użyć kluczy konta, osadzając je w aplikacjach klienckich podczas programowania. W miarę postępu poza programowaniem zdecydowanie zaleca się przejście do mechanizmu uwierzytelniania, który jest na poziomie produkcyjnym, obsługiwanym przez tokeny dostępu lub uwierzytelnianie użytkowników firmy Microsoft Entra. Aby uzyskać klucz konta do programowania, odwiedź konto usługi Azure Spatial Anchors i przejdź do karty "Klucze".

Dowiedz się więcej o klasie SessionConfiguration .

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

Tokeny dostępu

Tokeny dostępu to bardziej niezawodna metoda uwierzytelniania za pomocą usługi Azure Spatial Anchors. Szczególnie podczas przygotowywania aplikacji do wdrożenia produkcyjnego. Podsumowaniem tego podejścia jest skonfigurowanie usługi zaplecza, za pomocą którego aplikacja kliencka może bezpiecznie się uwierzytelniać. Interfejsy usługi zaplecza z usługą AAD w czasie wykonywania oraz z usługą Bezpiecznego tokenu usługi Azure Spatial Anchors w celu żądania tokenu dostępu. Ten token jest następnie dostarczany do aplikacji klienckiej i używany w zestawie SDK do uwierzytelniania za pomocą usługi Azure Spatial Anchors.

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

Jeśli token dostępu nie jest ustawiony, musisz obsłużyć TokenRequired zdarzenie lub zaimplementować tokenRequired metodę w protokole delegata.

Zdarzenie można obsługiwać synchronicznie, ustawiając właściwość na argumentach zdarzeń.

Dowiedz się więcej o interfejsie TokenRequiredListener .

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

Jeśli musisz wykonać pracę asynchroniczną w procedurze obsługi, możesz odroczyć ustawienie tokenu, żądając deferral obiektu, a następnie wykonując go, tak jak w poniższym przykładzie.

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

Uwierzytelnianie Microsoft Entra

Usługa Azure Spatial Anchors umożliwia również aplikacjom uwierzytelnianie za pomocą tokenów microsoft Entra ID (Active Directory). Na przykład możesz użyć tokenów firmy Microsoft Entra do integracji z usługą Azure Spatial Anchors. Jeśli przedsiębiorstwo utrzymuje użytkowników w identyfikatorze Entra firmy Microsoft, możesz podać token firmy Microsoft Entra w zestawie SDK usługi Azure Spatial Anchors. Dzięki temu można uwierzytelniać się bezpośrednio w usłudze Azure Spatial Anchors dla konta należącego do tej samej dzierżawy firmy Microsoft Entra.

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

Podobnie jak w przypadku tokenów dostępu, jeśli nie ustawiono tokenu entra firmy Microsoft, musisz obsługiwać zdarzenie TokenRequired lub zaimplementować metodę tokenRequired w protokole delegata.

Zdarzenie można obsługiwać synchronicznie, ustawiając właściwość na argumentach zdarzeń.

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

Jeśli musisz wykonać pracę asynchroniczną w procedurze obsługi, możesz odroczyć ustawienie tokenu, żądając deferral obiektu, a następnie wykonując go, tak jak w poniższym przykładzie.

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

Konfigurowanie sesji

Wywołaj polecenie Start() , aby umożliwić sesji przetwarzanie danych środowiska.

Aby obsłużyć zdarzenia zgłaszane przez sesję, dołącz procedurę obsługi zdarzeń.

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

Podawanie ramek do sesji

Sesja zakotwiczenia przestrzennego działa przez mapowanie przestrzeni wokół użytkownika. Dzięki temu można określić, gdzie znajdują się kotwice. Platformy mobilne (iOS i Android) wymagają natywnego wywołania kanału informacyjnego aparatu w celu uzyskania ramek z biblioteki AR platformy. Z kolei urządzenie HoloLens stale skanuje środowisko, więc nie ma potrzeby określonego wywołania, takiego jak na platformach mobilnych.

    mCloudSession.processFrame(mSession.update());

Przekazywanie opinii użytkownikowi

Możesz napisać kod do obsługi zaktualizowanego zdarzenia sesji. To zdarzenie jest uruchamiane za każdym razem, gdy sesja poprawia zrozumienie otoczenia. Umożliwia to:

  • Użyj klasy , aby przekazać użytkownikowi UserFeedback opinię w miarę przemieszczania się urządzenia, a sesja aktualizuje zrozumienie środowiska. W tym celu
  • Określ, w jakim momencie jest wystarczająco dużo śledzonych danych przestrzennych, aby utworzyć kotwice przestrzenne. Określasz to za pomocą polecenia ReadyForCreateProgress lub RecommendedForCreateProgress. Gdy ReadyForCreateProgress wartość jest wyższa niż 1, mamy wystarczającą ilość danych, aby zapisać kotwicę przestrzenną w chmurze, chociaż zalecamy poczekanie, aż RecommendedForCreateProgress wartość będzie powyżej 1, aby to zrobić.

Dowiedz się więcej o interfejsie 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()));
    });

Tworzenie kotwicy przestrzennej chmury

Aby utworzyć kotwicę przestrzenną w chmurze, należy najpierw utworzyć kotwicę w systemie AR platformy, a następnie utworzyć odpowiednik chmury. Należy użyć CreateAnchorAsync() metody .

Dowiedz się więcej o klasie 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);
    }

Jak opisano wcześniej, przed próbą utworzenia nowej zakotwiczenia przestrzennej chmury potrzebne są wystarczające dane środowiska. Oznacza to ReadyForCreateProgress , że musi być powyżej 1, choć zalecamy poczekanie RecommendedForCreateProgress powyżej 1, aby to zrobić.

    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);
    }

Ustawianie właściwości

Podczas zapisywania kotwic przestrzennych w chmurze możesz dodać pewne właściwości. Podobnie jak typ zapisywanego obiektu lub podstawowe właściwości, takie jak to, czy powinno być włączone na potrzeby interakcji. Może to być przydatne podczas odnajdywania: można natychmiast renderować obiekt dla użytkownika, na przykład ramkę obrazu z pustą zawartością. Następnie inne pobieranie w tle pobiera dodatkowe szczegóły stanu, na przykład obraz do wyświetlenia w ramce.

    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);
    // ...

Aktualizowanie właściwości

Aby zaktualizować właściwości na kotwicy, należy użyć UpdateAnchorProperties() metody . Jeśli co najmniej dwa urządzenia próbują zaktualizować właściwości dla tej samej kotwicy w tym samym czasie, użyjemy optymistycznego modelu współbieżności. Oznacza to, że pierwszy zapis wygra. Wszystkie inne operacje zapisu otrzymają błąd "Współbieżność": przed ponowną próbą konieczne będzie odświeżenie właściwości.

    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);
    }

Nie można zaktualizować lokalizacji kotwicy po jej utworzeniu w usłudze — musisz utworzyć nową kotwicę i usunąć ją, aby śledzić nową pozycję.

Jeśli nie musisz lokalizować kotwicy, aby zaktualizować jej właściwości, możesz użyć GetAnchorPropertiesAsync() metody , która zwraca CloudSpatialAnchor obiekt z właściwościami.

    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);
    }

Ustaw wygaśnięcie

Istnieje również możliwość skonfigurowania kotwicy tak, aby wygasała automatycznie w danej dacie w przyszłości. Gdy kotwica wygaśnie, nie będzie już znajdować się ani aktualizować. Wygaśnięcie można ustawić tylko po utworzeniu kotwicy przed zapisaniem jej w chmurze. Aktualizowanie wygasania później nie jest możliwe. Jeśli podczas tworzenia kotwicy nie ustawiono żadnego wygaśnięcia, kotwica wygaśnie tylko po ręcznym usunięciu.

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

Lokalizowanie kotwicy przestrzennej chmury

Możliwość zlokalizowania wcześniej zapisanej kotwicy przestrzennej chmury jest jedną z głównych przyczyn korzystania z usługi Azure Spatial Anchors. W tym celu używamy "Obserwatorów". W danym momencie można używać tylko jednego obserwatora; wielu obserwatorów nie jest obsługiwanych. Istnieje kilka różnych sposobów (nazywanych również strategiami lokalizowania zakotwiczenia) obserwator może zlokalizować kotwicę przestrzenną chmury. Możesz użyć jednej strategii na obserwatorze naraz.

Uwaga

Za każdym razem, gdy znajdziesz kotwicę, usługa Azure Spatial Anchors podejmie próbę użycia zebranych danych środowiska w celu rozszerzenia informacji wizualnych na kotwicy. Jeśli masz problemy z lokalizowaniem kotwicy, warto utworzyć kotwicę, a następnie zlokalizować ją kilka razy z różnych kątów i warunków oświetlenia.

Jeśli lokalizujesz kotwice przestrzenne chmury według identyfikatora, możesz przechowywać identyfikator zakotwiczenia przestrzennego w chmurze w usłudze zaplecza aplikacji i udostępnić go wszystkim urządzeniom, które mogą je prawidłowo uwierzytelniać. Aby zapoznać się z tym przykładem, zobacz Samouczek: udostępnianie kotwic przestrzennych między urządzeniami.

Utwórz wystąpienie AnchorLocateCriteria obiektu, ustaw identyfikatory, których szukasz, i wywołaj metodę CreateWatcher w sesji, podając element AnchorLocateCriteria.

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

Po utworzeniu obserwatora AnchorLocated zdarzenie zostanie wyzwolone dla każdej żądanej kotwicy. To zdarzenie jest uruchamiane, gdy znajduje się kotwica lub jeśli nie można znaleźć kotwicy. Jeśli taka sytuacja się stanie, przyczyna zostanie podana w stanie . Po przetworzeniu wszystkich kotwic dla obserwatora, znalezieniu lub nieponalezieniu zdarzenia LocateAnchorsCompleted zdarzenie zostanie wyzwolony. Istnieje limit 35 identyfikatorów na obserwatora.

Dowiedz się więcej o interfejsie 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;
        }
    });

Usuwanie kotwic

Usuwanie kotwic, gdy nie jest już używane, jest dobrym rozwiązaniem, które należy uwzględnić na wczesnym etapie procesu programowania i praktyk, aby zachować czyszczenie zasobów platformy Azure.

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

Wstrzymywanie, resetowanie lub zatrzymywanie sesji

Aby tymczasowo zatrzymać sesję, możesz wywołać metodę Stop(). Spowoduje to zatrzymanie wszystkich obserwatorów i przetwarzania środowiska, nawet jeśli wywołasz metodę ProcessFrame(). Następnie można wywołać Start() polecenie w celu wznowienia przetwarzania. Podczas wznawiania dane środowiska przechwytywane w sesji są zachowywane.

    mCloudSession.stop();

Aby zresetować dane środowiska przechwycone w sesji, możesz wywołać metodę Reset().

    mCloudSession.reset();

Aby prawidłowo wyczyścić po sesji, wywołaj metodę close().

    mCloudSession.close();

Następne kroki

W tym przewodniku przedstawiono sposób tworzenia i lokalizowania kotwic przy użyciu zestawu SDK usługi Azure Spatial Anchors. Aby dowiedzieć się więcej na temat relacji kotwicy, przejdź do następnego przewodnika.