Jak tworzyć i lokalizować kotwice przy użyciu usługi Azure Spatial Anchors w języku C++/NDK
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 SDK usługi Azure Spatial Anchors w języku C++/NDK do:
- 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 zestawu Android Native Development Kit.
- Podstawowa wiedza na temat arcore.
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 na temat struktury CloudSpatialAnchorSession .
std::shared_ptr<CloudSpatialAnchorSession> cloudSession_;
// In your view handler
cloudSession_ = std::make_shared<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 na temat struktury SessionConfiguration .
auto configuration = cloudSession_->Configuration();
configuration->AccountKey(R"(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 = cloudSession_->Configuration();
configuration->AccessToken(R"(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 .
auto accessTokenRequiredToken = cloudSession_->TokenRequired([](auto&&, auto&& args) {
args->AccessToken(R"(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.
auto accessTokenRequiredToken = cloudSession_->TokenRequired([this](auto&&, auto&& args) {
std::shared_ptr<CloudSpatialAnchorSessionDeferral> deferral = args->GetDeferral();
MyGetTokenAsync([&deferral, &args](std::string const& myToken) {
if (myToken != nullptr) 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 = cloudSession_->Configuration();
configuration->AuthenticationToken(R"(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ń.
auto accessTokenRequiredToken = cloudSession_->AccessTokenRequired([](auto&&, auto&& args) {
args->AuthenticationToken(R"(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.
auto accessTokenRequiredToken = cloudSession_->TokenRequired([this](auto&&, auto&& args) {
std::shared_ptr<CloudSpatialAnchorSessionDeferral> deferral = args->GetDeferral();
MyGetTokenAsync([&deferral, &args](std::string const& myToken) {
if (myToken != nullptr) 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 .
cloudSession_->Session(ar_session_);
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 .
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
lubRecommendedForCreateProgress
. GdyReadyForCreateProgress
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 .
auto sessionUpdatedToken = cloudSession_->SessionUpdated([this](auto&&, auto&& args) {
auto status = args->Status();
if (status->UserFeedback() == SessionUserFeedback::None) return;
std::ostringstream str;
str << std::fixed << std::setw(2) << std::setprecision(0)
<< R"(Feedback: )" << FeedbackToString(status.UserFeedback()) << R"( -)"
<< R"( Recommend Create=)" << (status->RecommendedForCreateProgress() * 100) << R"(%)";
feedback_ = str.str();
});
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 na temat struktury CloudSpatialAnchor .
// Create a local anchor, perhaps by hit-testing and creating an ARAnchor
ArAnchor* localAnchor;
ArHitResultList* hit_result_list = nullptr;
ArHitResultList_create(ar_session_, &hit_result_list);
CHECK(hit_result_list);
ArFrame_hitTest(ar_session_, ar_frame_, 0.5, 0.5, hit_result_list);
int32_t hit_result_list_size = 0;
ArHitResultList_getSize(ar_session_, hit_result_list, &hit_result_list_size);
if (hit_result_list_size == 0) {
ArHitResultList_destroy(hit_result_list);
return;
}
ArHitResult* ar_hit = nullptr;
ArHitResult_create(ar_session_, &ar_hit);
// The hitTest method sorts the resulting list by increasing distance from the camera
// The first hit result will usually be the most relevant when responding to user input
ArHitResultList_getItem(ar_session_, hit_result_list, 0, ar_hit);
if (ArHitResult_acquireNewAnchor(ar_session_, ar_hit, &localAnchor) != AR_SUCCESS) return;
ArTrackingState tracking_state = AR_TRACKING_STATE_STOPPED;
ArAnchor_getTrackingState(ar_session_, localAnchor, &tracking_state);
if (tracking_state != AR_TRACKING_STATE_TRACKING) {
ArAnchor_release(localAnchor);
ArHitResult_destroy(ar_hit);
return;
}
ArHitResult_destroy(ar_hit);
ar_hit = nullptr;
ArHitResultList_destroy(hit_result_list);
hit_result_list = nullptr;
// 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.
std::shared_ptr<CloudSpatialAnchor> cloudAnchor = std::make_shared<CloudSpatialAnchor>();
cloudAnchor->LocalAnchor(localAnchor);
cloudSession_->CreateAnchorAsync(cloudAnchor, [this, cloudAnchor](Status status) {
std::ostringstream str;
if (status != Status::OK) {
str << "Save Failed: " << std::to_string(static_cast<uint32_t>(status));
feedback_ = str.str();
return;
}
str << R"(Created a cloud anchor with ID=)" << cloudAnchor->Identifier();
feedback_ = str.str();
});
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 .
cloudSession_->GetSessionStatusAsync([this](Status status, const std::shared_ptr<SessionStatus>& value) {
if (status != Status::OK) {
std::ostringstream str;
str << "Session status error: " << std::to_string(static_cast<uint32_t>(status));
feedback_ = str.str();
return;
}
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 .
std::shared_ptr<CloudSpatialAnchor> cloudAnchor = std::make_shared<CloudSpatialAnchor>();
cloudAnchor->LocalAnchor(localAnchor);
auto properties = cloudAnchor->AppProperties();
properties->Insert(R"(model-type)", R"(frame)");
properties->Insert(R"(label)", R"(my latest picture)");
cloudSession_->CreateAnchorAsync(cloudAnchor, [this, cloudAnchor](Status status) {
// ...
});
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 .
std::shared_ptr<CloudSpatialAnchor> anchor = /* locate your anchor */;
auto properties = anchor->AppProperties();
properties->Insert(R"(last-user-access)", R"(just now)");
cloudSession_->UpdateAnchorPropertiesAsync(anchor, [this](Status status) {
if (status != Status::OK) {
std::ostringstream str;
str << "Updating Properties Failed: " << std::to_string(static_cast<uint32_t>(status));
feedback_ = str.str();
}
});
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 .
cloudSession_->GetAnchorPropertiesAsync(R"(anchorId)", [this](Status status, const std::shared_ptr<CloudSpatialAnchor>& anchor) {
if (status != Status::OK) {
std::ostringstream str;
str << "Getting Properties Failed: " << std::to_string(static_cast<uint32_t>(status));
feedback_ = str.str();
return;
}
if (anchor != nullptr) {
auto properties = anchor->AppProperties();
properties->Lookup(R"(last-user-access)") = R"(just now)";
cloudSession_->UpdateAnchorPropertiesAsync(anchor, [this](Status status) {
// ...
});
}
});
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 .
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::chrono::system_clock::time_point oneWeekFromNow = now + std::chrono::hours(7 * 24);
const int64_t oneWeekFromNowUnixEpochTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(oneWeekFromNow.time_since_epoch()).count();
cloudAnchor->Expiration(oneWeekFromNowUnixEpochTimeMs);
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.
- Znajdź kotwice według identyfikatora.
- Znajdź kotwice połączone z wcześniej zlokalizowaną kotwicą. Relacje kotwicy można znaleźć tutaj.
- Znajdź kotwicę przy użyciu ponownej lokalizacji coarse.
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 .
auto criteria = std::make_shared<AnchorLocateCriteria>();
criteria->Identifiers({ R"(id1)", R"(id2)", R"(id3)" });
auto cloudSpatialAnchorWatcher = 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 AnchorLocated .
auto anchorLocatedToken = cloudSession_->AnchorLocated([this](auto&&, auto&& args) {
switch (args->Status()) {
case LocateAnchorStatus::Located: {
std::shared_ptr<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;
}
});
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 .
cloudSession_->DeleteAnchorAsync(cloudAnchor, [this](Status status) {
// 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 .
cloudSession_->Stop();
Aby zresetować dane środowiska przechwycone w sesji, możesz wywołać metodę Reset()
.
Dowiedz się więcej o metodzie Reset .
cloudSession_->Reset();
Aby prawidłowo wyczyścić po wydaniu sesji wszystkie odwołania.
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.