C++/WinRT で Azure Spatial Anchors を使用してアンカーを作成して配置する方法How to create and locate anchors using Azure Spatial Anchors in C++/WinRT

Azure Spatial Anchors を使用して、世界中の異なるデバイス間でアンカーを共有できます。Azure Spatial Anchors allow you to share anchors in the world between different devices. これは複数の異なる開発環境をサポートしています。It supports several different development environments. この記事では、Azure Spatial Anchors SDK を C++/WinRT で使用する方法について説明します。次のことを行います。In this article, we'll dive into how to use the Azure Spatial Anchors SDK, in C++/WinRT, to:

  • Azure Spatial Anchors セッションを正しく設定して管理する。Correctly set up and manage an Azure Spatial Anchors session.
  • ローカル アンカーのプロパティを作成して設定する。Create and set properties on local anchors.
  • それらをクラウドにアップロードする。Upload them to the cloud.
  • クラウドの空間アンカーを検索して削除する。Locate and delete cloud spatial anchors.

前提条件Prerequisites

このガイドを完了するには、以下が必要です。To complete this guide, make sure you have:

クロス プラットフォーム

セッションの初期化Initialize the session

SDK のメイン エントリ ポイントは、セッションを表すクラスです。The main entry point for the SDK is the class representing your session. 通常は、ビューとネイティブ AR セッションを管理するクラス内のフィールドを宣言します。Typically you'll declare a field in the class that manages your view and native AR session.

CloudSpatialAnchorSession クラスの詳細を確認してください。Learn more about the CloudSpatialAnchorSession class.

    SpatialAnchorsFactory m_asafactory{ nullptr };
    CloudSpatialAnchorSession m_cloudSession{ nullptr };
    winrt::com_ptr<::IUnknown> unk;
    winrt::check_hresult(ASACreateFactory(unk.put()));
    m_asafactory = unk.as<SpatialAnchorsFactory>();
    m_cloudSession = m_asafactory.CreateCloudSpatialAnchorSession();

認証の設定Set up authentication

サービスにアクセスするには、アカウント キー、アクセス トークン、または Azure Active Directory 認証トークンを提供する必要があります。To access the service, you need to provide an account key, access token, or Azure Active Directory auth token.

アカウント キーAccount Keys

アカウント キーは、アプリケーションが Azure Spatial Anchors サービスで認証できるようにするための資格情報です。Account Keys are a credential that allows your application to authenticate with the Azure Spatial Anchors service. アカウント キーの使用目的は、すぐに開始できるようにサポートすることです。The intended purpose of Account Keys is to help you get started quickly. 特にアプリケーションの Azure Spatial Anchors との統合の開発フェーズ時などがこれに該当します。Especially during the development phase of your application's integration with Azure Spatial Anchors. そのようなものとして、開発中にクライアント アプリケーションにアカウント キーを埋め込んで使用できます。As such, you can use Account Keys by embedding them in your client applications during development. 開発の先のフェーズに進むときには、実稼働レベルであるか、アクセス トークンによりサポートされるか、または Azure Active Directory ベースのユーザー認証である認証メカニズムに移行することを強く推奨します。As you progress beyond development, it's highly recommended to move to an authentication mechanism that is production-level, supported by Access Tokens, or Azure Active Directory user authentication. 開発のためにアカウント キーを取得するには、Azure Spatial Anchors アカウントにアクセスし、[キー] タブに移動します。To get an Account Key for development, visit your Azure Spatial Anchors account, and navigate to the "Keys" tab.

SessionConfiguration クラスの詳細を確認してください。Learn more about the SessionConfiguration class.

    auto configuration = m_cloudSession.Configuration();
    configuration.AccountKey(LR"(MyAccountKey)");

アクセス トークンAccess Tokens

アクセス トークンは、Azure Spatial Anchors で認証するためのより堅牢な方法です。Access Tokens are a more robust method to authenticate with Azure Spatial Anchors. 特に運用環境デプロイメントのアプリケーションを準備するきにはそのように言えます。Especially as you prepare your application for a production deployment. このアプローチの概要は、クライアント アプリケーションが安全に認証できるバックエンド サービスを設定することです。The summary of this approach is to set up a back-end service that your client application can securely authenticate with. バック エンド サービスは、実行時に AAD と連動し、Azure Spatial Anchors の Secure Token Service と連動してアクセス トークンを要求します。Your back-end service interfaces with AAD at runtime and with the Azure Spatial Anchors Secure Token Service to request an Access Token. このトークンは、クライアント アプリケーションに配信され、SDK で Azure Spatial Anchors で認証するために使用されます。This token is then delivered to the client application and used in the SDK to authenticate with Azure Spatial Anchors.

    auto configuration = m_cloudSession.Configuration();
    configuration.AccessToken(LR"(MyAccessToken)");

アクセス トークンが設定されていない場合は、TokenRequired イベントを処理するか、デリゲート プロトコルに tokenRequired メソッドを実装する必要があります。If an access token isn't set, you must handle the TokenRequired event, or implement the tokenRequired method on the delegate protocol.

イベント引数のプロパティを設定することで、イベントを同期的に処理できます。You can handle the event synchronously by setting the property on the event arguments.

TokenRequiredDelegate デリゲートの詳細を確認してください。Learn more about the TokenRequiredDelegate delegate.

    m_accessTokenRequiredToken = m_cloudSession.TokenRequired(winrt::auto_revoke, [](auto&&, auto&& args) {
        args.AccessToken(LR"(MyAccessToken)");
    });

ハンドラーで非同期操作を実行する必要がある場合は、次の例のように deferral オブジェクトを要求してこれを完了することによって、トークンの設定を延期することができます。If you need to execute asynchronous work in your handler, you can defer setting the token by requesting a deferral object and then completing it, as in the following example.

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

Azure Active Directory 認証Azure Active Directory Authentication

Azure Spatial Anchors を使用すると、アプリケーションは Azure AD (Active Directory) のユーザー トークンでも認証できるようになります。Azure Spatial Anchors also allows applications to authenticate with user Azure AD (Active Directory) tokens. たとえば、Azure AD トークンを使用して Azure Spatial Anchors と統合することができます。For example, you can use Azure AD tokens to integrate with Azure Spatial Anchors. 企業が Azure AD でユーザーを管理している場合は、Azure Spatial Anchors SDK で Azure AD のユーザー トークンを提供できます。If an Enterprise maintains users in Azure AD, you can supply a user Azure AD token in the Azure Spatial Anchors SDK. このように操作することで、同じ Azure AD テナントの一部であるアカウントの Azure Spatial Anchors サービスに直接認証することができます。Doing so allows you to authenticate directly to the Azure Spatial Anchors service for an account that's part of the same Azure AD tenant.

    auto configuration = m_cloudSession.Configuration();
    configuration.AuthenticationToken(LR"(MyAuthenticationToken)");

アクセス トークンの場合と同様、Azure AD トークンが設定されていない場合は、TokenRequired イベントを処理するか、デリゲート プロトコルに tokenRequired メソッドを実装する必要があります。Like with access tokens, if an Azure AD token isn't set, you must handle the TokenRequired event, or implement the tokenRequired method on the delegate protocol.

イベント引数のプロパティを設定することで、イベントを同期的に処理できます。You can handle the event synchronously by setting the property on the event arguments.

    m_accessTokenRequiredToken = m_cloudSession.TokenRequired(winrt::auto_revoke, [](auto&&, auto&& args) {
        args.AuthenticationToken(LR"(MyAuthenticationToken)");
    });

ハンドラーで非同期操作を実行する必要がある場合は、次の例のように deferral オブジェクトを要求してこれを完了することによって、トークンの設定を延期することができます。If you need to execute asynchronous work in your handler, you can defer setting the token by requesting a deferral object and then completing it, as in the following example.

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

セッションの設定Set up the session

セッションにおいて環境データを処理できるようにするには、Start() を呼び出します。Invoke Start() to enable your session to process environment data.

セッションによって発生したイベントを処理するには、イベント ハンドラーをアタッチします。To handle events raised by your session, attach an event handler.

Start メソッドの詳細を確認してください。Learn more about the Start method.

    m_cloudSession.Start();

セッションにフレームを提供するProvide frames to the session

空間アンカー セッションは、ユーザーの周りに空白をマップすることによって機能します。The spatial anchor session works by mapping the space around the user. そうすることで、アンカーの場所を決定しやすくなります。Doing so helps to determine where anchors are located. モバイル プラットフォーム (iOS と Android) には、プラットフォームの AR ライブラリからフレームを取得するためにカメラ フィードへのネイティブ呼び出しが必要です。Mobile platforms (iOS & Android) require a native call to the camera feed to obtain frames from your platform's AR library. これに対し、Hololens は環境を継続的にスキャンするため、Mobile の場合と異なり特定の呼び出しは必要ありません。In contrast, HoloLens is constantly scanning the environment, so there's no need for a specific call like with Mobile.

ProcessFrame メソッドの詳細を確認してください。Learn more about the ProcessFrame method.

    m_cloudSession->ProcessFrame(ar_frame_);

ユーザーへのフィードバックの提供Provide feedback to the user

セッションが更新されるイベントを処理するために、コードを記述できます。You can write code to handle the session updated event. セッションによるユーザーの環境の理解が深まるたびに、このイベントが発生します。This event fires every time the session improves its understanding of your surroundings. これにより、次のことが可能になります。Doing so, allows you to:

  • デバイスが移動し、セッションで環境の把握状況が変わったら、ユーザーにフィードバックを提供する。Provide feedback to the user as the device moves and the session updates its environment understanding.
  • 空間アンカーを作成または特定できるだけの追跡済み空間データを確保できるのはどの時点かを判断する。詳細については後の手順で説明します。Determine at what point there's enough tracked spatial data to create or locate spatial anchors - we'll learn more at a later step.

SessionUpdatedDelegate デリゲートの詳細を確認してください。Learn more about the SessionUpdatedDelegate delegate.

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

クラウド空間アンカーの作成Create a cloud spatial anchor

クラウド アンカーを作成するには、最初にプラットフォームの AR システムにアンカーを作成した後、対応するアンカーをクラウド上に作成します。To create a cloud anchor, you first create an anchor in your platform's AR system, and then create a cloud counterpart. CreateAnchorAsync() メソッドを使用します。You use the CreateAnchorAsync() method.

CloudSpatialAnchor クラスの詳細を確認してください。Learn more about the CloudSpatialAnchor class.

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

新しいクラウド アンカーの作成を試みる前に、十分な環境データが取得されている必要があります。You need sufficient environment data captured before trying to create a new cloud anchor.

GetSessionStatusAsync メソッドの詳細を確認してください。Learn more about the GetSessionStatusAsync method.

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

プロパティの設定Set properties

クラウド アンカーを保存するときには、いくつかのプロパティを追加することを選択できます。You may choose to add some properties when saving your cloud anchors. これは保存されるオブジェクトの型や、相互作用に対して有効にすべきかどうかなどの基本プロパティなどです。Like the type of object being saved, or basic properties like whether it should be enabled for interaction. そのようにすると検出時に役立つ場合があります。空のコンテンツの画像フレームなど、ユーザー向けのオブジェクトをすぐにレンダリングできます。Doing so can be useful upon discovery: you can immediately render the object for the user, for example a picture frame with blank content. 次に、バックグラウンドでの別のダウンロードにより、フレームに表示されるピクチャなどの、追加の状態の詳細が取得されます。Then, a different download in the background gets additional state details, for example, the picture to display in the frame.

AppProperties メソッドの詳細を確認してください。Learn more about the AppProperties method.

    CloudSpatialAnchor cloudAnchor = m_asafactory.CreateCloudSpatialAnchor();
    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);

プロパティを更新するUpdate properties

アンカーでプロパティを更新するには、UpdateAnchorProperties() メソッドを使用します。To update the properties on an anchor, you use the UpdateAnchorProperties() method. 2 つ以上のデバイスが同じアンカーのプロパティを同時に更新する場合は、オプティミスティック同時実行制御モデルを使用します。If two or more devices try to update properties for the same anchor at the same time, we use an optimistic concurrency model. これは、最初の書き込みが優先されることを意味します。Which means that the first write will win. その他のすべての書き込みには、「同時実行」エラーが発生します。再試行する前に、プロパティの更新が必要になります。All other writes will get a "Concurrency" error: a refresh of the properties would be needed before trying again.

UpdateAnchorPropertiesAsync メソッドの詳細を確認してください。Learn more about the UpdateAnchorPropertiesAsync method.

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

アンカーがサービス上で作成された後は、アンカーの位置を更新することはできません。新しい位置を追跡するには、新しいアンカーを作成し、古いアンカーを削除する必要があります。You can't update the location of an anchor once it has been created on the service - you must create a new anchor and delete the old one to track a new position.

プロパティを更新するためにアンカーを探知する必要がない場合は、CloudSpatialAnchor オブジェクトをプロパティと共に返す GetAnchorPropertiesAsync() メソッドを使用できます。If you don't need to locate an anchor to update its properties, you can use the GetAnchorPropertiesAsync() method, which returns a CloudSpatialAnchor object with properties.

GetAnchorPropertiesAsync メソッドの詳細を確認してください。Learn more about the GetAnchorPropertiesAsync method.

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

有効期限の設定Set expiration

未来の特定の日付で有効期限が自動的に切れるようにアンカーを構成することもできます。It's also possible to configure your anchor to expire automatically at a given date in the future. 有効期限が切れたアンカーは、特定も更新もできなくなります。When an anchor expires, it will no longer be located or updated. 有効期限は、アンカーが作成されたときにのみ設定できます。Expiration can only be set when the anchor is created. 後で有効期限を更新することはできません。Updating expiration afterwards isn't possible. そのため、有効期限はクラウドに保存する前に設定できます。So, you can set its expiration before saving it to the cloud.

Expiration メソッドの詳細を確認してください。Learn more about the Expiration method.

    const int64_t oneWeekFromNowInHours = 7 * 24;
    const DateTime oneWeekFromNow = DateTime::clock::now() + std::chrono::hours(oneWeekFromNowInHours);
    cloudAnchor.Expiration(oneWeekFromNow);

クラウド空間アンカーを見つけるLocate a cloud spatial anchor

Azure Spatial Anchors ライブラリを使用する主要な理由の 1 つに、以前にアップロードしたクラウド空間アンカーを検索できることが挙げられます。Being able to locate a previously uploaded cloud spatial anchor is one of the prime reasons for using the Azure Spatial Anchors library. クラウド空間アンカーを見つけるには、識別子を知っておく必要があります。To locate cloud spatial anchors, you'll need to know their identifiers. アンカー ID はアプリケーションのバックエンド サービスに格納でき、それを適切に認証できるすべてのデバイスにアクセスできます。Anchor IDs can be stored in your application's back-end service, and accessible to all devices that can properly authenticate to it. この例のついては、「チュートリアル:デバイス間で空間アンカーを共有する」をご覧ください。For an example of this see Tutorial: Share Spatial Anchors across devices.

AnchorLocateCriteria オブジェクトをインスタンス化し、検索する識別子を設定します。次に AnchorLocateCriteria を指定することでセッション上の CreateWatcher メソッドを呼び出します。Instantiate an AnchorLocateCriteria object, set the identifiers you're looking for, and invoke the CreateWatcher method on the session by providing your AnchorLocateCriteria.

CreateWatcher メソッドの詳細を確認してください。Learn more about the CreateWatcher method.

    AnchorLocateCriteria criteria = m_asafactory.CreateAnchorLocateCriteria();
    criteria.Identifiers({ LR"(id1)", LR"(id2)", LR"(id3)" });
    auto cloudSpatialAnchorWatcher = m_cloudSession.CreateWatcher(criteria);

監視が作成された後、要求されたすべてのアンカーに対して AnchorLocated イベントが発生します。After your watcher is created, the AnchorLocated event will fire for every anchor requested. このイベントは、アンカーが探知されたとき、またはアンカーを探知できなかった場合に発生します。This event fires when an anchor is located, or if the anchor can't be located. このような状況が発生した場合は、その理由が状態に示されます。If this situation happens, the reason will be stated in the status. 監視のすべてのアンカーが (探知されたかどうかを問わず) 処理された後、LocateAnchorsCompleted イベントが発生します。After all anchors for a watcher are processed, found or not found, then the LocateAnchorsCompleted event will fire. 識別子の上限は、Watcher 1 つあたり 35 個です。There is a limit of 35 identifiers per watcher.

AnchorLocatedDelegate デリゲートの詳細を確認してください。Learn more about the AnchorLocatedDelegate delegate.

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

アンカーの削除Delete anchors

クラウド空間アンカーを削除するには、DeleteAnchor() メソッドを使用します。To delete a cloud spatial anchor, you use the DeleteAnchor() method. 使用されなくなった場合のアンカーの削除は、開発のプロセスおよびプラクティスにおいて、早い段階で取り入れることをお勧めします。Deleting anchors when no longer used is a good practice to include early on in your development process and practices. そうすることで、リソースがクリーンアップされた状態を保ちます。Doing so keeps resources cleaned up. さらに、Azure Spatial Anchors を無料で使用できていても、将来は価格設定が変更される可能性があります。Moreover, even though you can use Azure Spatial Anchors free of charge, pricing may change in the future. プレビュー期間中の料金について詳しくは、価格に関するページをご覧ください。You can find details about pricing during Preview on our pricing page.

DeleteAnchorAsync メソッドの詳細を確認してください。Learn more about the DeleteAnchorAsync method.

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

セッションの一時停止、リセット、停止Pause, reset, or stop the session

セッションを一時的に停止するために、Stop() を呼び出すことができます。To stop the session temporarily, you can invoke Stop(). そうすることで、ProcessFrame() を呼び出した場合でも、あらゆるウォッチャーや環境処理を停止できます。Doing so will stop any watchers and environment processing, even if you invoke ProcessFrame(). 次に Start() を呼び出して、処理を再開できます。You can then invoke Start() to resume processing. 再開するとき、既にセッションでキャプチャされた環境データは保持されます。When resuming, environment data already captured in the session is maintained.

Stop メソッドの詳細を確認してください。Learn more about the Stop method.

    m_cloudSession.Stop();

セッションでキャプチャされた環境データをリセットするために、Reset() を呼び出すことができます。To reset the environment data that has been captured in your session, you can invoke Reset().

Reset メソッドの詳細を確認してください。Learn more about the Reset method.

    m_cloudSession.Reset();

セッションがすべての参照を解放した後に適切にクリーンアップするようにします。To clean up properly after a session release all references.

    m_cloudSession = nullptr;

次の手順Next steps

このガイドでは、Azure Spatial Anchors SDK を使用してアンカーを作成および探知する方法について学習しました。In this guide, you learned about how to create and locate anchors using the Azure Spatial Anchors SDK. アンカーのリレーションシップの詳細については、次のガイドに進んでください。To learn more about anchor relationships, continue to the next guide.