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

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 C++/WinRT, aby:

  • 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 C++ i interfejsów API środowisko wykonawcze systemu Windows.

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 .

    CloudSpatialAnchorSession m_cloudSession{ nullptr };

    m_cloudSession = 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 .

    auto configuration = m_cloudSession.Configuration();
    configuration.AccountKey(LR"(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.

    auto configuration = m_cloudSession.Configuration();
    configuration.AccessToken(LR"(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 na temat delegata TokenRequiredDelegate .

    m_accessTokenRequiredToken = m_cloudSession.TokenRequired(winrt::auto_revoke, [](auto&&, auto&& args) {
        args.AccessToken(LR"(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.

    m_accessTokenRequiredToken = m_cloudSession.TokenRequired(winrt::auto_revoke, [this](auto&&, auto&& args) {
        auto deferral = args.GetDeferral();
        MyGetTokenAsync([&deferral, &args](winrt::hstring const& myToken) {
            if (!myToken.empty()) args.AccessToken(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.

    auto configuration = m_cloudSession.Configuration();
    configuration.AuthenticationToken(LR"(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ń.

    m_accessTokenRequiredToken = m_cloudSession.TokenRequired(winrt::auto_revoke, [](auto&&, auto&& args) {
        args.AuthenticationToken(LR"(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.

    m_accessTokenRequiredToken = m_cloudSession.TokenRequired(winrt::auto_revoke, [this](auto&&, auto&& args) {
        auto deferral = args.GetDeferral();
        MyGetTokenAsync([&deferral, &args](winrt::hstring const& myToken) {
            if (!myToken.empty()) args.AuthenticationToken(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ń.

Dowiedz się więcej o metodzie Start .

    m_cloudSession.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.

Dowiedz się więcej o metodzie ProcessFrame .

    m_cloudSession->ProcessFrame(ar_frame_);

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 na temat delegata SessionUpdatedDelegate .

    m_sessionUpdatedToken = m_cloudSession.SessionUpdated(winrt::auto_revoke, [this](auto&&, auto&& args)
    {
        auto status = args.Status();
        if (status.UserFeedback() == SessionUserFeedback::None) return;
        m_feedback = LR"(Feedback: )" + FeedbackToString(status.UserFeedback()) + LR"( -)" +
            LR"( Recommend Create=)" + FormatPercent(status.RecommendedForCreateProgress() * 100.f);
    });

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 .

    // Initialization
    SpatialStationaryFrameOfReference m_stationaryReferenceFrame = nullptr;
    HolographicDisplay defaultHolographicDisplay = HolographicDisplay::GetDefault();
    SpatialLocator spatialLocator = defaultHolographicDisplay.SpatialLocator();
    m_stationaryReferenceFrame = spatialLocator.CreateStationaryFrameOfReferenceAtCurrentLocation();

    // Create a local anchor, perhaps by positioning a SpatialAnchor a few meters in front of the user
    SpatialAnchor localAnchor{ nullptr };
    PerceptionTimestamp timestamp = PerceptionTimestampHelper::FromHistoricalTargetTime(DateTime::clock::now());
    SpatialCoordinateSystem currentCoordinateSystem = m_attachedReferenceFrame.GetStationaryCoordinateSystemAtTimestamp(timestamp);
    SpatialPointerPose pose = SpatialPointerPose::TryGetAtTimestamp(currentCoordinateSystem, timestamp);

    // Get the gaze direction relative to the given coordinate system.
    const float3 headPosition = pose.Head().Position();
    const float3 headDirection = pose.Head().ForwardDirection();

    // The anchor is positioned two meter(s) along the user's gaze direction.
    constexpr float distanceFromUser = 2.0f; // meters
    const float3 gazeAtTwoMeters = headPosition + (distanceFromUser * headDirection);

    localAnchor = SpatialAnchor::TryCreateRelativeTo(currentCoordinateSystem, gazeAtTwoMeters);

    // 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 = CloudSpatialAnchor();
    cloudAnchor.LocalAnchor(localAnchor);
    co_await m_cloudSession.CreateAnchorAsync(cloudAnchor);
    m_feedback = LR"(Created a cloud anchor with ID=)" + cloudAnchor.Identifier();

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ć.

Dowiedz się więcej o metodzie GetSessionStatusAsync .

    SessionStatus status = co_await m_cloudSession.GetSessionStatusAsync();
    if (value.RecommendedForCreateProgress() < 1.0f) return;
    // Issue the creation request ...

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.

Dowiedz się więcej o metodzie AppProperties .

    CloudSpatialAnchor cloudAnchor = CloudSpatialAnchor();
    cloudAnchor.LocalAnchor(localAnchor);
    auto properties = m_cloudAnchor.AppProperties();
    properties.Insert(LR"(model-type)", LR"(frame)");
    properties.Insert(LR"(label)", LR"(my latest picture)");
    co_await m_cloudSession.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.

Dowiedz się więcej o metodzie UpdateAnchorPropertiesAsync .

    CloudSpatialAnchor anchor = /* locate your anchor */;
    anchor.AppProperties().Insert(LR"(last-user-access)", LR"(just now)");
    co_await m_cloudSession.UpdateAnchorPropertiesAsync(anchor);

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.

Dowiedz się więcej o metodzie GetAnchorPropertiesAsync .

    CloudSpatialAnchor anchor = co_await m_cloudSession.GetAnchorPropertiesAsync(LR"(anchorId)");
    if (anchor != nullptr)
    {
        anchor.AppProperties().Insert(LR"(last-user-access)", LR"(just now)");
        co_await m_cloudSession.UpdateAnchorPropertiesAsync(anchor);
    }

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.

Dowiedz się więcej o metodzie Expiration .

    const int64_t oneWeekFromNowInHours = 7 * 24;
    const DateTime oneWeekFromNow = DateTime::clock::now() + std::chrono::hours(oneWeekFromNowInHours);
    cloudAnchor.Expiration(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.

Dowiedz się więcej o metodzie CreateWatcher .

    AnchorLocateCriteria criteria = AnchorLocateCriteria();
    criteria.Identifiers({ LR"(id1)", LR"(id2)", LR"(id3)" });
    auto cloudSpatialAnchorWatcher = m_cloudSession.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 na temat delegata AnchorLocatedDelegate .

    m_anchorLocatedToken = m_cloudSession.AnchorLocated(winrt::auto_revoke, [this](auto&&, auto&& args)
    {
        switch (args.Status())
        {
            case LocateAnchorStatus::Located:
            {
                CloudSpatialAnchor foundAnchor = args.Anchor();
            }
                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;
        }
    });

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.

Dowiedz się więcej o metodzie DeleteAnchorAsync .

    co_await m_cloudSession.DeleteAnchorAsync(cloudAnchor);
    // Perform any processing you may want when delete finishes

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.

Dowiedz się więcej o metodzie Stop .

    m_cloudSession.Stop();

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

Dowiedz się więcej o metodzie Reset .

    m_cloudSession.Reset();

Aby prawidłowo wyczyścić po wydaniu sesji wszystkie odwołania.

    m_cloudSession = nullptr;

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.