Создание и поиск привязок с помощью Пространственных привязок Azure в Swift

Пространственные привязки Azure позволяют вам совместно использовать привязки на различных устройствах. Служба поддерживает несколько сред разработки. Из этой статьи вы узнаете, как использовать пакет SDK Пространственных привязок Azure в Swift, чтобы выполнять следующие действия:

  • правильно настраивать сеанс Пространственных привязок Azure и управлять им;
  • создавать и настраивать свойства в локальных привязках;
  • передавать их в облако;
  • обнаруживать и удалять пространственные привязки в облаке.

Предварительные условия

Для работы с этим руководством вам потребуются:

Кроссплатформенная поддержка

Инициализация сеанса

Основной точкой входа для пакета SDK является класс, представляющий ваш сеанс. Обычно нужно объявить поле в классе, который управляет представлением и нативным сеансом AR.

Дополнительные сведения см. в статье о классе ASACloudSpatialAnchorSession.

    var _cloudSession : ASACloudSpatialAnchorSession? = nil
    // In your view handler
    _cloudSession = ASACloudSpatialAnchorSession()

Настройка проверки подлинности

Чтобы получить доступ к службе, необходимо указать ключ учетной записи, маркер доступа или маркер проверки подлинности Azure Active Directory. Дополнительные сведения об этом можно также получить на странице с описанием концепции проверки подлинности.

Ключи учетных записей

Ключи учетных записей — это учетные данные, позволяющие приложению проходить проверку подлинности в службе "Пространственные привязки Azure". Назначение ключей учетных записей — помочь быстро приступить к работе. Это важно на этапе разработки интеграции приложения с Пространственными привязками Azure. Таким образом, вы можете использовать ключи учетной записи, внедряя их в клиентские приложения во время разработки. По мере развития процесса разработки настоятельно рекомендуем перейти на механизм проверки подлинности на производственном уровне, поддерживаемый маркерами доступа, или проверку подлинности пользователя Azure Active Directory. Чтобы получить ключ учетной записи для разработки, откройте учетную запись Пространственных привязок Azure и перейдите на вкладку "Ключи".

Дополнительные сведения см. в статье о классе ASASessionConfiguration.

    _cloudSession!.configuration.accountKey = "MyAccountKey"

Маркеры доступа

Маркеры доступа — это более надежный метод проверки подлинности с помощью Пространственных привязок Azure. Такой метод наиболее актуален при подготовке приложения к рабочему развертыванию. Краткое изложение этого подхода заключается в настройке внутренней службы, с помощью которой клиентское приложение может безопасно выполнять проверку подлинности. Внутренняя служба взаимодействует с AAD во время выполнения и со службой маркера безопасности Пространственных привязок Azure для запроса маркера доступа. Затем этот маркер доставляется клиентскому приложению и используется в пакете SDK для проверки подлинности с помощью Пространственных привязок Azure.

    _cloudSession!.configuration.accessToken = "MyAccessToken"

Если маркер доступа не задан, необходимо выполнить обработку события TokenRequired или реализовать метод tokenRequired для протокола делегирования.

Событие можно обрабатывать синхронно, задав свойство аргументов события.

Дополнительные сведения см. в статье о методе протокола tokenRequired.

    internal func tokenRequired(_ cloudSession:ASACloudSpatialAnchorSession!, _ args:ASATokenRequiredEventArgs!) {
        args.accessToken = "MyAccessToken"
    }

Если нужно выполнить асинхронные операции в обработчике, можете отложить установку маркера, запросив объект deferral, а затем завершить установку, как показано в следующем примере.

    internal func tokenRequired(_ cloudSession:ASACloudSpatialAnchorSession!, _ args:ASATokenRequiredEventArgs!) {
        let deferral = args.getDeferral()
        myGetTokenAsync( withCompletionHandler: { (myToken: String?) in
            if (myToken != nil) {
                args.accessToken = myToken
            }
            deferral?.complete()
        })
    }

Аутентификация Azure Active Directory

Пространственные привязки Azure также позволяют приложениям проходить проверку подлинности с помощью маркеров пользователя Azure AD (Active Directory). Например, вы можете использовать маркеры Azure AD для интеграции с Пространственными привязками Azure. Если предприятие поддерживает пользователей в Azure AD, вы можете указать маркер пользователя Azure AD в пакете SDK для Пространственных привязок Azure. Это позволит вам проходить проверку подлинности непосредственно в службе "Пространственные привязки Azure" для учетной записи, являющейся частью того же клиента Azure AD.

    _cloudSession!.configuration.authenticationToken = "MyAuthenticationToken"

Как и в случае с маркерами доступа, если маркер Azure AD не задан, необходимо выполнить обработку события TokenRequired или реализовать метод tokenRequired для протокола делегирования.

Событие можно обрабатывать синхронно, задав свойство аргументов события.

    internal func tokenRequired(_ cloudSession:ASACloudSpatialAnchorSession!, _ args:ASATokenRequiredEventArgs!) {
        args.authenticationToken = "MyAuthenticationToken"
    }

Если нужно выполнить асинхронные операции в обработчике, можете отложить установку маркера, запросив объект deferral, а затем завершить установку, как показано в следующем примере.

    internal func tokenRequired(_ cloudSession:ASACloudSpatialAnchorSession!, _ args:ASATokenRequiredEventArgs!) {
        let deferral = args.getDeferral()
        myGetTokenAsync( withCompletionHandler: { (myToken: String?) in
            if (myToken != nil) {
                args.authenticationToken = myToken
            }
            deferral?.complete()
        })
    }

Настройка библиотеки

Вызовите Start(), чтобы разрешить обработку данных среды в сеансе.

Чтобы обрабатывать события, вызванные сеансом, задайте для свойства delegate сеанса объект, например представление. В этом объекте должен реализовываться протокол SSCCloudSpatialAnchorSessionDelegate.

Дополнительные сведения о методе start .

    _cloudSession!.session = self.sceneView.session;
    _cloudSession!.delegate = self;
    _cloudSession!.start()

Предоставление кадров для сеанса

Сеанс пространственной привязки работает путем сопоставления пространства вокруг пользователя. Это помогает определить, где находятся привязки. Для мобильных платформ (iOS & Android) требуется собственный вызов веб-канала камеры для получения кадров из библиотеки AR вашей платформы. HoloLens, напротив, постоянно сканирует среду, поэтому нет необходимости в конкретном вызове, например на мобильных платформах.

Дополнительные сведения см. в статье о методе processFrame.

    _cloudSession?.processFrame(self.sceneView.session.currentFrame)

Предоставление отзыва пользователю

Вы можете написать код для управления событием обновления сеанса. Это событие срабатывает каждый раз, когда сеанс улучшает распознавание окружающей среды. Это позволит вам:

  • использовать класс UserFeedback для формирования обратной связи с пользователем при перемещении устройства и обновлении сеансом его распознавания среды. Для этого сделайте следующее.
  • Определите, на каком этапе отслеживаемых пространственных данных достаточно для создания пространственных привязок. Это можно определить с помощью ReadyForCreateProgress или RecommendedForCreateProgress. Когда ReadyForCreateProgress больше 1, у нас достаточно данных для сохранения облачной пространственной привязки, но мы рекомендуем подождать, пока 1 не превысит RecommendedForCreateProgress.

Дополнительные сведения см. в статье о методе протокола sessionUpdated.

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

Создание облачной пространственной привязки

Чтобы создать облачную пространственную привязку, сначала создайте привязку в системе AR на своей платформе, а затем создайте прототип облака. Воспользуйтесь методом CreateAnchorAsync().

Дополнительные сведения см. в статье о классе ASACloudSpatialAnchor.

    // 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!)"
    })

Как было сказано ранее, прежде чем создавать новую пространственную привязку в облаке необходимо получить достаточное количество данных об окружающей среде. Это означает, что ReadyForCreateProgress должен быть больше 1, поэтому мы рекомендуем подождать, пока RecommendedForCreateProgress превысит 1.

Дополнительные сведения см. в разделе о методе getSessionStatusWithCompletionHandler.

    _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 ...
    })

Настройка свойств

Вы можете добавить некоторые свойства при сохранении пространственных привязок облака. Это может быть тип сохраняемого объекта или основные свойства, например, следует ли их включать для взаимодействия. Это может быть полезно при обнаружении: можно сразу же отобразить объект для пользователя, например, кадр с пустым содержимым. Затем в фоновом режиме загружается дополнительная информация о состоянии, например изображение, отображаемое в кадре.

Дополнительные сведения о свойстве appProperties .

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

Обновление свойств

Обновить свойства привязки можно с помощью метода UpdateAnchorProperties(). Если два или более устройств пытаются одновременно обновить свойства одной и той же привязки, мы используем модель оптимистической блокировки. Это означает, что преимущество отдается первой операции записи. Для всех остальных операций записи поступит сообщение об ошибке параллелизма. Прежде чем повторять попытку, нужно будет обновить свойства.

Дополнительные сведения см. в статье о методе updateAnchorProperties.

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

Невозможно обновить расположение привязки после ее создания в службе. Чтобы отслеживать новое расположение, создайте новую привязку и удалите старую.

Если вам не нужно искать привязку для обновления ее свойств, вы можете использовать метод GetAnchorPropertiesAsync(), который возвращает объект CloudSpatialAnchor со свойствами.

Дополнительные сведения см. в статье о методе getAnchorProperties.

    _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
                // ...
            })
        }
    })

Срок действия

Можно также настроить для привязки автоматическое истечение срока действия в определенный момент времени в будущем. После истечения срока действия привязку больше нельзя будет найти или обновить. Срок действия можно задать только при создании привязки и перед ее сохранением в облаке. После этого изменить срок действия нельзя. Если во время создания привязки не задать срок ее действия, то она продолжит действовать, пока не будетудалена вручную.

Дополнительные сведения см. в статье о свойстве expiration.

    let secondsInAWeek = 60.0 * 60.0 * 24.0 * 7.0
    let oneWeekFromNow = Date(timeIntervalSinceNow: secondsInAWeek)
    cloudAnchor!.expiration = oneWeekFromNow

Поиск облачной пространственной привязки

Одна из основных причин использования Пространственных привязок Azure — возможность искать ранее сохраненную облачную пространственную привязку. Для этого мы используем "Наблюдатели". Вы можете использовать только один наблюдатель за раз; несколько наблюдателей не поддерживаются. Существует несколько различных способов (также известных как стратегии поиска привязок) наблюдатель может найти облачную пространственную привязку. За один раз можно использовать одну стратегию для наблюдателя.

  • Нахождение привязок по идентификатору.
  • Нахождение привязок, подключенных к ранее найденной привязке. Больше узнать о связях привязок можно здесь.
  • Нахождение привязки, используя Простое уточнение расположения.

Примечание

Каждый раз при обнаружении привязки Пространственные привязки Azure попытаются использовать собранные данные среды, чтобы расширить визуальные сведения о привязке. Если у вас возникли проблемы с нахождением привязки, можно создать привязку, а затем определить ее несколько раз, используя разные углы и условия освещения.

При поиске облачных пространственных привязок по идентификатору можно сохранить идентификатор облачной пространственной привязки в серверной службе приложения и сделать его доступным для всех устройств, которые могут правильно пройти проверку подлинности. Пример см. в Руководстве по совместному использованию службы "Пространственные привязки" на разных устройствах.

Создайте экземпляр объекта AnchorLocateCriteria, задайте идентификаторы, которые вы ищете, и в сеансе вызовите метод CreateWatcher, предоставив AnchorLocateCriteria.

Дополнительные сведения см. в статье о методе createWatcher.

    let criteria = ASAAnchorLocateCriteria()!
    criteria.identifiers = [ "id1", "id2", "id3" ]
    _cloudSession!.createWatcher(criteria)

Когда вы создадите наблюдатель, для каждой запрошенной привязки будет срабатывать событие AnchorLocated. Это событие срабатывает, если привязка обнаружена или если ее не удалось найти. В последнем случае причина будет указана в области состояния. Когда для наблюдателя будут обработаны, найдены или не найдены все привязки, сработает событие LocateAnchorsCompleted. Максимальное количество идентификаторов на наблюдателя — 35.

Дополнительные сведения см. в статье о методе протокола anchorLocated.

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

Удаление привязок

Мы рекомендуем удалять неиспользуемые привязки в ходе разработки. Так ваши ресурсы Azure будут очищенными.

Дополнительные сведения см. в разделе о методе delete.

    _cloudSession?.delete(cloudAnchor!, withCompletionHandler: { (error: Error?) in
        // Perform any processing you may want when delete finishes
    })

Приостановка, сброс или остановка сеанса

Чтобы временно остановить сеанс, можно вызвать Stop(). Это приведет к прерыванию обработки наблюдателей и среды даже при вызове ProcessFrame(). Затем можно вызвать Start(), чтобы возобновить обработку. При возобновлении обработанные в сеансе данные сохраняются.

Дополнительные сведения о методе stop .

    _cloudSession!.stop()

Чтобы очистить данные среды, записанные в сеансе, можете вызвать функцию Reset().

Дополнительные сведения см. в статье о методе reset.

    _cloudSession!.reset()

Для правильной очистки после выпуска сеанса всех ссылок.

    _cloudSession = nil

Дальнейшие действия

Из этого руководства вы узнали о том, как создавать и находить привязки с использованием пакета SDK для службы "Пространственные привязки Azure". Чтобы узнать больше о связях между привязками, перейдите к следующему руководству.