Erstellen von und Suchen nach Ankern mit Azure Spatial Anchors in Swift
Azure Spatial Anchors ermöglicht die weltweite gemeinsame Verwendung von Ankern durch verschiedene Geräte. Der Dienst unterstützt verschiedene Entwicklungsumgebungen. In diesem Artikel wird erläutert, wie das Azure Spatial Anchors SDK in Swift für die folgenden Aufgaben verwendet werden kann:
- Ordnungsgemäßes Einrichten und Verwalten einer Azure Spatial Anchors-Sitzung.
- Erstellen und Festlegen von Eigenschaften für lokale Anker.
- Hochladen von Ankern in die Cloud.
- Suchen nach und Löschen von räumlichen Cloudankern.
Voraussetzungen
Um diese Anleitung durchzuführen, stellen Sie sicher, dass Folgendes erfüllt ist:
- Sie haben die Informationen unter Azure Spatial Anchors-Übersicht gelesen.
- Sie haben eine der fünfminütigen Schnellstartanleitungen absolviert.
- Sie verfügen über Grundkenntnisse zu Swift.
- Sie verfügen über Grundkenntnisse zu ARKit.
Initialisieren der Sitzung
Der Haupteinstiegspunkt für das SDK ist die Klasse, die die Sitzung darstellt. In der Regel müssen Sie ein Feld in der Klasse deklarieren, die Ihre Ansicht und die native AR-Sitzung verwaltet.
Erfahren Sie mehr über die ASACloudSpatialAnchorSession-Klasse.
var _cloudSession : ASACloudSpatialAnchorSession? = nil
// In your view handler
_cloudSession = ASACloudSpatialAnchorSession()
Einrichten der Authentifizierung
Um auf den Dienst zugreifen zu können, müssen Sie einen Kontoschlüssel, ein Zugriffstoken oder ein Microsoft Entra-Authentifizierungstoken angeben. Weitere Informationen hierzu finden Sie auf der Konzeptseite für die Authentifizierung.
Kontoschlüssel
Kontoschlüssel sind eine Anmeldeinformationen, die es Ihrer Anwendung ermöglichen, sich beim Azure Spatial Anchors-Dienst zu authentifizieren. Der Zweck von Kontoschlüsseln besteht darin, Ihnen einen schnellen Einstieg zu ermöglichen. Vor allem während der Entwicklungsphase der Integration Ihrer Anwendung mit Azure Spatial Anchors. Sie können Kontoschlüssel verwenden, indem Sie sie während der Entwicklung in Ihre Clientanwendungen einbetten. Nach Abschluss der Entwicklung wird dringend empfohlen, zu einem Authentifizierungsmechanismus für die Produktionsebene zu wechseln, der von Zugriffstoken oder Microsoft Entra-basierter Benutzerauthentifizierung unterstützt wird. Um einen Kontoschlüssel für die Entwicklung zu erhalten, besuchen Sie Ihr Azure Spatial Anchors-Konto, und navigieren Sie zur Registerkarte „Schlüssel“.
Erfahren Sie mehr über die ASASessionConfiguration-Klasse.
_cloudSession!.configuration.accountKey = "MyAccountKey"
Zugriffstoken
Zugriffstoken sind eine robustere Methode zur Authentifizierung bei Azure Spatial Anchors. Vor allem, wenn Sie Ihre Anwendung für eine Produktionsbereitstellung vorbereiten. Die Zusammenfassung dieses Ansatzes besteht darin, einen Back-End-Dienst einzurichten, bei dem sich Ihre Clientanwendung sicher authentifizieren kann. Ihr Back-End-Dienst kommuniziert zur Runtime mit AAD und mit dem STS-Dienst (Secure Token Service) von Azure Spatial Anchors, um ein Zugriffstoken anzufordern. Dieses Token wird dann der Clientanwendung bereitgestellt und im SDK zur Authentifizierung bei Azure Spatial Anchors verwendet.
_cloudSession!.configuration.accessToken = "MyAccessToken"
Wenn ein Zugriffstoken nicht festgelegt ist, müssen Sie das TokenRequired
-Ereignis behandeln oder die tokenRequired
-Methode im Delegatenprotokoll implementieren.
Sie können das Ereignis synchron behandeln, indem Sie die Eigenschaft für die Ereignisargumente festlegen.
Erfahren Sie mehr über die tokenRequired-Protokollmethode.
internal func tokenRequired(_ cloudSession:ASACloudSpatialAnchorSession!, _ args:ASATokenRequiredEventArgs!) {
args.accessToken = "MyAccessToken"
}
Wenn Sie in Ihrem Handler asynchrone Arbeit ausführen müssen, können Sie die Einstellung des Token verzögern, indem Sie ein deferral
-Objekt anfordern und es dann wie im folgenden Beispiel abschließen.
internal func tokenRequired(_ cloudSession:ASACloudSpatialAnchorSession!, _ args:ASATokenRequiredEventArgs!) {
let deferral = args.getDeferral()
myGetTokenAsync( withCompletionHandler: { (myToken: String?) in
if (myToken != nil) {
args.accessToken = myToken
}
deferral?.complete()
})
}
Microsoft Entra-Authentifizierung
Bei Azure Spatial Anchors können Anwendungen sich auch mit Microsoft Entra ID-Benutzertoken (Active Directory) authentifizieren. Sie können beispielsweise Microsoft Entra-Token für die Integration in Azure Spatial Anchors verwenden. Wenn ein Unternehmen Benutzer*innen in Microsoft Entra ID verwaltet, können Sie ein Microsoft Entra-Benutzertoken im Azure Spatial Anchors-SDK bereitstellen. Auf diese Weise ermöglichen Sie für Konten, die zum gleichen Microsoft Entra-Mandanten gehören, eine direkte Authentifizierung beim Azure Spatial Anchors-Dienst.
_cloudSession!.configuration.authenticationToken = "MyAuthenticationToken"
Wenn ein Microsoft Entra-Token nicht festgelegt ist, müssen Sie wie bei Zugriffstoken das TokenRequired-Ereignis behandeln oder die tokenRequired-Methode im Delegatenprotokoll implementieren.
Sie können das Ereignis synchron behandeln, indem Sie die Eigenschaft für die Ereignisargumente festlegen.
internal func tokenRequired(_ cloudSession:ASACloudSpatialAnchorSession!, _ args:ASATokenRequiredEventArgs!) {
args.authenticationToken = "MyAuthenticationToken"
}
Wenn Sie in Ihrem Handler asynchrone Arbeit ausführen müssen, können Sie die Einstellung des Token verzögern, indem Sie ein deferral
-Objekt anfordern und es dann wie im folgenden Beispiel abschließen.
internal func tokenRequired(_ cloudSession:ASACloudSpatialAnchorSession!, _ args:ASATokenRequiredEventArgs!) {
let deferral = args.getDeferral()
myGetTokenAsync( withCompletionHandler: { (myToken: String?) in
if (myToken != nil) {
args.authenticationToken = myToken
}
deferral?.complete()
})
}
Einrichten der Bibliothek
Rufen Sie Start()
auf, damit Ihre Sitzung Umgebungsdaten verarbeitet.
Legen Sie zum Verarbeiten von Ereignissen, die von der Sitzung ausgelöst werden, die delegate
-Eigenschaft der Sitzung auf ein Objekt wie z.B. Ihre Ansicht fest. Dieses Objekt muss das SSCCloudSpatialAnchorSessionDelegate
-Protokoll implementieren.
Erfahren Sie mehr über die start-Methode.
_cloudSession!.session = self.sceneView.session;
_cloudSession!.delegate = self;
_cloudSession!.start()
Bereitstellen von Rahmen für die Sitzung
Bei einer Sitzung mit Raumankern wird die Umgebung zugeordnet, in der sich der Benutzer gerade befindet. Auf diese Weise lässt sich ermitteln, wo sich Anker befinden. Mobile Plattformen (iOS und Android) erfordern einen nativen Aufruf des Kamerafeeds, um Rahmen aus der AR-Bibliothek Ihrer Plattform abzurufen. Im Gegensatz dazu scannt HoloLens die Umgebung ständig, sodass kein gesonderter Aufruf wie bei mobilen Plattformen erforderlich ist.
Erfahren Sie mehr über die processFrame-Methode.
_cloudSession?.processFrame(self.sceneView.session.currentFrame)
Bereitstellen von Feedback für Benutzer
Sie können Code schreiben, um das aktualisierte Sitzungsereignis zu verarbeiten. Dieses Ereignis wird jedes Mal ausgelöst, wenn die Sitzung ihr Verständnis für Ihre Umgebung verbessert. Auf diese Weise können Sie Folgendes erreichen:
- Verwenden Sie die Klasse
UserFeedback
, um Feedback für Benutzer bereitzustellen, wenn sich das Gerät bewegt und die Sitzung die Informationen zur Umgebung aktualisiert. Gehen Sie dazu folgendermaßen vor: - Bestimmen Sie, an welchem Punkt genügend räumliche Daten erfasst wurden, um Raumanker zu erstellen. Verwenden Sie hierzu
ReadyForCreateProgress
oderRecommendedForCreateProgress
. SobaldReadyForCreateProgress
größer 1 ist, liegen genügend Daten zum Speichern eines cloudbasierten Raumankers vor. Es empfiehlt sich jedoch, damit zu warten, bisRecommendedForCreateProgress
größer 1 ist.
Erfahren Sie mehr über die sessionUpdated-Protokollmethode.
internal func sessionUpdated(_ cloudSession:ASACloudSpatialAnchorSession!, _ args:ASASessionUpdatedEventArgs!) {
let status = args.status!
if (status.userFeedback.isEmpty) {
return
}
_feedback = "Feedback: \(FeedbackToString(userFeedback:status.userFeedback)) - Recommend Create=\(status.recommendedForCreateProgress * 100)"
}
Erstellen eines cloudbasierten Raumankers
Um einen cloudbasierten Raumanker zu erstellen, erstellen Sie zunächst einen Anker im AR-System Ihrer Plattform und dann ein Cloudgegenstück. Sie verwenden die CreateAnchorAsync()
-Methode.
Erfahren Sie mehr über die ASACloudSpatialAnchor-Klasse.
// Create a local anchor, perhaps by hit-testing and creating an ARAnchor
var localAnchor : ARAnchor? = nil
let hits = self.sceneView.session.currentFrame?.hitTest(CGPoint(x:0.5, y:0.5), types: ARHitTestResult.ResultType.estimatedHorizontalPlane)
if (hits!.count == 0) return
// 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
localAnchor = ARAnchor(transform:hits![0].worldTransform)
self.sceneView.session.add(anchor: _localAnchor!)
// 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.
var cloudAnchor : ASACloudSpatialAnchor? = nil
cloudAnchor = ASACloudSpatialAnchor()
cloudAnchor!.localAnchor = localAnchor
_cloudSession?.createAnchor(cloudAnchor!, withCompletionHandler: { (error: Error?) in
if (error != nil) {
_feedback = "Save Failed:\(error!.localizedDescription)"
return
}
_feedback = "Created a cloud anchor with ID=\(cloudAnchor!.identifier!)"
})
Wie bereits erwähnt, benötigen Sie ausreichende Umgebungsdaten, um einen neuen cloudbasierten Raumanker erstellen zu können. Das bedeutet, dass ReadyForCreateProgress
größer 1 sein muss. Es empfiehlt sich jedoch, zu warten, bis RecommendedForCreateProgress
größer 1 ist.
Erfahren Sie mehr über die getStatusWithCompletionHandler-Methode.
_cloudSession?.getStatusWithCompletionHandler( { (value:ASASessionStatus, error:Error?) in
if (error != nil) {
_feedback = "Session status error:\(error!.localizedDescription)"
return
}
if (value!.recommendedForCreateProgress <> 1.0) {
return
}
// Issue the creation request ...
})
Eigenschaften festlegen
Beim Speichern Ihrer cloudbasierten Raumanker können Sie einige Eigenschaften hinzufügen. Beispiele: die Art des gespeicherten Objekts oder grundlegende Eigenschaften wie etwa das Ermöglichen von Interaktion. Solche Eigenschaften können beim Ermitteln nützlich sein: Sie können ein Objekt sofort für den Benutzer rendern – z.B. als Bildrahmen mit leerem Inhalt. Ein anderer Download im Hintergrund stellt dann zusätzliche Statusdetails bereit, beispielsweise das Bild, das im Rahmen angezeigt werden soll.
Erfahren Sie mehr über die appProperties-Eigenschaft.
var cloudAnchor : ASACloudSpatialAnchor? = nil
cloudAnchor = ASACloudSpatialAnchor()
cloudAnchor!.localAnchor = localAnchor
cloudAnchor!.appProperties = [ "model-type" : "frame", "label" : "my latest picture" ]
_cloudSession?.createAnchor(cloudAnchor!, withCompletionHandler: { (error: Error?) in
// ...
})
Aktualisieren von Eigenschaften
Um die Eigenschaften eines Ankers zu aktualisieren, verwenden Sie die UpdateAnchorProperties()
-Methode. Wenn zwei oder mehr Geräte gleichzeitig versuchen, die Eigenschaften für den gleichen Anker zu aktualisieren, verwenden wir ein Modell der optimistischen Nebenläufigkeit. Das bedeutet, dass der erste Schreibvorgang gewinnt. Bei allen anderen Schreibvorgängen tritt ein Parallelitätsfehler auf: Vor einem erneuten Versuch müssen die Eigenschaften aktualisiert werden.
Erfahren Sie mehr über die updateAnchorProperties-Methode.
var anchor : ASACloudSpatialAnchor? = /* locate your anchor */;
anchor!.appProperties["last-user-access"] = "just now"
_cloudSession?.updateAnchorProperties(anchor!, withCompletionHandler: { (error:Error?) in
if (error != nil) {
_feedback = "Updating Properties Failed:\(error!.localizedDescription)"
}
})
Sie können den Speicherort eines Ankers nicht aktualisieren, nachdem er für den Dienst erstellt wurde – Sie müssen einen neuen Anker erstellen und den alten löschen, um eine neue Position zu verfolgen.
Wenn Sie einen Anker nicht suchen müssen, um seine Eigenschaften zu aktualisieren, können Sie die GetAnchorPropertiesAsync()
-Methode verwenden, die ein CloudSpatialAnchor
-Objekt mit Eigenschaften zurückgibt.
Erfahren Sie mehr über die getAnchorProperties-Methode.
_cloudSession?.getAnchorProperties("anchorId", withCompletionHandler: { (anchor:SCCCloudSpatialAnchor?, error:Error?) in
if (error != nil) {
_feedback = "Getting Properties Failed:\(error!.localizedDescription)"
}
if (anchor != nil) {
anchor!.appProperties["last-user-access"] = "just now"
_cloudSession?.updateAnchorProperties(anchor!, withCompletionHandler: { (error:Error?) in
// ...
})
}
})
Ablaufdatum festlegen
Sie können Ihren Anker auch so konfigurieren, dass er an einem bestimmten Datum automatisch abläuft. Wenn ein Anker abläuft, wird er nicht mehr lokalisiert oder aktualisiert. Ein Ablauf kann nur beim Erstellen des Ankers festgelegt werden, bevor er in der Cloud gespeichert wird. Eine nachträgliche Aktualisierung des Ablaufdatums ist nicht möglich. Wenn während der Erstellung des Ankers kein Ablauf festgelegt wird, läuft der Anker nur ab, wenn er manuell gelöscht wird.
Erfahren Sie mehr über die expiration-Eigenschaft.
let secondsInAWeek = 60.0 * 60.0 * 24.0 * 7.0
let oneWeekFromNow = Date(timeIntervalSinceNow: secondsInAWeek)
cloudAnchor!.expiration = oneWeekFromNow
Lokalisieren eines cloudbasierten Raumankers
Die Möglichkeit, einen zuvor gespeicherten cloudbasierten Raumanker zu lokalisieren, ist einer der Hauptgründe für die Nutzung von Azure Spatial Anchors. Dazu verwenden wir "Watchers". Sie können jeweils nur einen Watcher verwenden. Mehrere Watchers werden nicht unterstützt. Es gibt verschiedene Möglichkeiten (auch bekannt als Anchor Locate Strategies) ein Watcher kann einen Cloudraumanker finden. Sie können jeweils eine Strategie pro Watcher verwenden.
- Lokalisieren von Ankern anhand des Bezeichners
- Lokalisieren von Ankern, die mit einem zuvor lokalisierten Anker verbunden sind. Informationen zu Ankerbeziehungen finden Sie hier.
- Lokalisieren eines Ankers unter Verwendung der ungefähren Standortbestimmung
Hinweis
Bei jeder Lokalisierung eines Ankers wird von Azure Spatial Anchors versucht, die erfassten Umgebungsdaten zu verwenden, um die visuellen Informationen des Ankers zu erweitern. Falls Sie beim Lokalisieren eines Ankers Probleme haben, kann es hilfreich sein, einen Anker zu erstellen und diesen dann mehrfach aus unterschiedlichen Winkeln und bei unterschiedlichen Lichtverhältnissen zu lokalisieren.
Wenn Sie cloudbasierte Raumanker anhand des Bezeichners lokalisieren, sollten Sie den Bezeichner des cloudbasierten Raumankers im Back-End-Dienst Ihrer Anwendung speichern und für alle Geräte verfügbar machen, die sich ordnungsgemäß authentifizieren können. Ein entsprechendes Beispiel finden Sie unter Tutorial: Freigeben von Raumankern für Geräte.
Instanziieren Sie ein AnchorLocateCriteria
-Objekt, legen Sie die zu suchenden IDs fest, und rufen Sie die CreateWatcher
-Methode für die Sitzung auf, indem Sie Ihr AnchorLocateCriteria
-Objekt angeben.
Erfahren Sie mehr über die createWatcher-Methode.
let criteria = ASAAnchorLocateCriteria()!
criteria.identifiers = [ "id1", "id2", "id3" ]
_cloudSession!.createWatcher(criteria)
Nachdem Ihr Watcher erstellt wurde, wird das AnchorLocated
-Ereignis für jeden angeforderten Anker ausgelöst. Dieses Ereignis wird sogar dann ausgelöst, wenn ein Anker gefunden wird, oder der Anker nicht gefunden werden kann. Wenn dies geschieht, wird die Ursache im Status angegeben. Nachdem alle Anker für einen Watcher – ob gefunden oder nicht gefunden – verarbeitet wurden, wird das LocateAnchorsCompleted
-Ereignis ausgelöst. Es besteht eine Beschränkung von 35 Bezeichner pro Watcher.
Erfahren Sie mehr über die anchorLocated-Protokollmethode.
internal func anchorLocated(_ cloudSession: ASACloudSpatialAnchorSession!, _ args: ASAAnchorLocatedEventArgs!) {
let status = args.status
switch (status) {
case ASALocateAnchorStatus.located:
let foundAnchor = args.anchor
// Go add your anchor to the scene...
break
case ASALocateAnchorStatus.alreadyTracked:
// This anchor has already been reported and is being tracked
break
case ASALocateAnchorStatus.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 ASALocateAnchorStatus.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
}
}
Löschen von Ankern
Das Löschen von Ankern, die nicht mehr verwendet werden, ist eine bewährte Methode, die Sie frühzeitig in Ihren Entwicklungsprozess und Ihre Praktiken einbeziehen sollten, damit Ihre Azure-Ressourcen bereinigt werden.
Erfahren Sie mehr über die delete-Methode.
_cloudSession?.delete(cloudAnchor!, withCompletionHandler: { (error: Error?) in
// Perform any processing you may want when delete finishes
})
Anhalten, Zurücksetzen oder Beenden einer Sitzung
Um eine Sitzung vorübergehend anzuhalten, können Sie Stop()
aufrufen. Damit werden alle Überwachungskomponenten und sämtliche Prozesse der Umgebungsverarbeitung angehalten, auch wenn Sie ProcessFrame()
aufrufen. Danach können Sie Start()
aufrufen, um die Verarbeitung fortzusetzen. Beim Fortsetzen werden alle in der Sitzung bereits erfassten Umgebungsdaten beibehalten.
Erfahren Sie mehr über die stop-Methode.
_cloudSession!.stop()
Um die Umgebungsdaten zurückzusetzen, die in der Sitzung erfasst wurden, können Sie Reset()
aufrufen.
Erfahren Sie mehr über die reset-Methode.
_cloudSession!.reset()
Zur ordnungsgemäßen Bereinigung nach einer Sitzung geben Sie alle Verweise frei.
_cloudSession = nil
Nächste Schritte
In dieser Anleitung haben Sie gelernt, wie Sie mit dem Azure Spatial Anchors SDK Anker erstellen und lokalisieren. Weitere Informationen zu Ankerbeziehungen finden Sie in der nächsten Anleitung.