Skip to content

Commit 61fd388

Browse files
authored
Merge pull request #67519 from MicrosoftDocs/release-pub-preview
Release pub preview
2 parents 4fe4cfe + dc35c90 commit 61fd388

File tree

93 files changed

+3854
-74
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+3854
-74
lines changed

articles/role-based-access-control/built-in-roles.md

+130-19
Large diffs are not rendered by default.

articles/role-based-access-control/resource-provider-operations.md

+171-55
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
title: Anchor relationships and way-finding in Azure Spatial Anchors | Microsoft Docs
3+
description: Describe the conceptual model behind anchor relationships. Describe the process of connecting anchors within a space, and the process of using the Nearby API to fulfill a way-finding scenario. After explaining the conceptual model, point developers to our sample apps that do nearby so they can get started implementing this scenario in their own apps.
4+
author: ramonarguelles
5+
manager: vicenterivera
6+
services: azure-spatial-anchors
7+
8+
ms.author: ramonarguelles
9+
ms.date: 02/24/2019
10+
ms.topic: conceptual
11+
ms.service: azure-spatial-anchors
12+
---
13+
# Anchor relationships and way-finding in Azure Spatial Anchors
14+
15+
Anchor relationships allow you to create connected anchors in a space and then ask questions about them like:
16+
17+
* Are there anchors nearby?
18+
* How far away are they?
19+
20+
## Examples
21+
22+
Some example use-cases you can enable with connected anchors include:
23+
24+
1. A worker needs to carry out a procedure that involves visiting various locations in an industrial factory. The factory has placed spatial anchors at each site involved in the procedure. A HoloLens or mobile app helps guide the worker from one location to the next. It would first ask for the spatial anchors that are nearby, and then guide the worker to the next location. The app displays visual indicators about the general direction and distance to the next location to complete the task.
25+
26+
2. A museum creates spatial anchors at public displays that together create a specific tour through the museum such as "A one-hour tour of essential public displays". When visitors are at one public display, they can open the museum's mixed reality app on their mobile device. Then, they would point their phone around the space and through a camera feed, and see the general direction and distance to the other public displays on the tour. As the user starts to walk towards one of the public displays, the app progressively updates the general direction and distance to help guide users there.
27+
28+
## Way-finding
29+
30+
Imagine the app is using "line-of-sight" direction and distance between anchors to provide guidance hints to users. We refer to this overall scenario as way-finding. It's important to note way-finding is different from turn-by-turn navigation. In turn-by-turn navigation, the users are guided around walls, through doors, and between floors. With way-finding, the user is provided hints about the general direction of the destination. But the user's inference or knowledge of the space also helps to navigate through the structure to the destination.
31+
32+
Building a way-finding experience involves preparing a space for the experience and developing an app that end users will interact with. The conceptual steps involved include:
33+
34+
1. Planning the space: Determine the locations within the space that participate in the way-finding experience. In the earlier examples, this activity might be completed by the factory supervisor or the museum tour coordinator.
35+
2. Connecting anchors: Someone visits the chosen locations and creates spatial anchors there. This task can be done with an admin mode of the end-user app or a different app entirely. Through this process, each anchor is connected or related to the others. These relationships are maintained in the service.
36+
3. Starting the end-user experience: The first step for end users is to locate one of the anchors using the app, which can be in any one of the chosen locations. Determining the locations where end users can enter the experience is part of designing the overall experience.
37+
4. Finding nearby anchors: Once the user has located one anchor, the app can request nearby anchors. This procedure returns a pose between the device and these anchors.
38+
5. Guiding the user: The app can take advantage of the pose to each of these anchors to render useful guidance hints about their general direction and distance. For instance, there might be an icon and arrow on a camera feed in a mobile app representing each potential destination as in the image below.
39+
6. Refining the guidance: As the user walks, the app can periodically calculate a new pose between the device and the destination anchor. The app continues to refine the guidance hints that help the user arrive at the destination.
40+
41+
![Meeting Spot](./media/meeting-spot.png)
42+
43+
## Connecting Anchors
44+
45+
To build a way-finding experience, you need to place connected anchors in the chosen locations. Below we'll assume this work is done by an admin of the app.
46+
47+
### Connecting Anchors in a single session
48+
49+
The steps involved in connecting anchors are:
50+
51+
1. The admin walks to the first location and creates Anchor A using a CloudSpatialAnchorSession.
52+
2. The admin walks to the second location while the underlying MR/AR platform continues to track the user.
53+
3. The admin creates Anchor B with the same CloudSpatialAnchorSession. Anchors A and B are now connected, and this relationship is maintained by the Azure Spatial Anchors service.
54+
4. Continue the procedure for all anchors that you want to connect.
55+
56+
### Multiple sessions
57+
58+
You can also connect spatial anchors over multiple sessions. This method allows you to create and connect some anchors at one time, and later create and connect more anchors. To connect anchors with multiple sessions:
59+
60+
1. The app creates some anchors in one CloudSpatialAnchorSession.
61+
2. Later, for instance on a different day, the app locates one of these anchors with a new CloudSpatialAnchorSession (for example Anchor A).
62+
3. The user walks to a new location, while the underlying MR/AR platform continues to track the user.
63+
4. Using same CloudSpatialAnchorSession, the user creates anchor C. Anchors A, B, and C are now connected and this relationship is maintained by Azure Spatial Anchors.
64+
5. You can continue this procedure for more anchors and more sessions over time.
65+
66+
### Verifying Anchor Connections
67+
68+
The app can verify that two anchors are connected by issuing a query for nearby anchors. When the result of the query contains the desired target anchor, then the app has confirmation that the anchors are connected. If they aren't connected, the app can retry the connection procedure again. Here are some reasons why anchors might fail to connect:
69+
70+
1. The underlying MR/AR tracker lost tracking during the process of connecting anchors.
71+
2. There was a network error communicating with the Azure Spatial Anchors service and the anchor connection couldn't be persisted.
72+
73+
### Sample code
74+
75+
You can see sample code that shows you how to connect anchors and do nearby queries. Refer to the Azure Spatial Anchors sample apps on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
---
2+
title: Create and locate anchors using Azure Spatial Anchors in C++/NDK | Microsoft Docs
3+
description: In-depth explanation of how to create and locate anchors using Azure Spatial Anchors in C++/NDK.
4+
author: ramonarguelles
5+
manager: vicenterivera
6+
services: azure-spatial-anchors
7+
8+
ms.author: ramonarguelles
9+
ms.date: 02/24/2019
10+
ms.topic: conceptual
11+
ms.service: azure-spatial-anchors
12+
# ms.reviewer: MSFT-alias-of-reviewer
13+
#Customer intent: As a mixed reality developer, I want and in-depth explanation of how to create and locate anchors using Azure Spatial Anchors in C++/NDK.
14+
---
15+
# Create and locate anchors using Azure Spatial Anchors in C++/NDK
16+
17+
> [!div class="op_single_selector"]
18+
> * [Unity](create-locate-anchors-unity.md)
19+
> * [Objective-C](create-locate-anchors-objc.md)
20+
> * [Swift](create-locate-anchors-swift.md)
21+
> * [Android Java](create-locate-anchors-java.md)
22+
> * [C++/NDK](create-locate-anchors-cpp-ndk.md)
23+
> * [C++/WinRT](create-locate-anchors-cpp-winrt.md)
24+
25+
Azure Spatial Anchors allow you to share anchors in the world between different devices. It has been tuned to work well with your choice of development environment. In this article, we'll dive into how to do it in C++/NDK.
26+
27+
[!INCLUDE [Start](../../../includes/spatial-anchors-create-locate-anchors-start.md)]
28+
29+
```cpp
30+
std::shared_ptr<CloudSpatialAnchorSession> cloudSession_;
31+
// In your view handler
32+
cloudSession_ = std::make_shared<CloudSpatialAnchorSession>();
33+
```
34+
35+
[!INCLUDE [Account Keys](../../../includes/spatial-anchors-create-locate-anchors-account-keys.md)]
36+
37+
```cpp
38+
auto configuration = cloudSession_->Configuration();
39+
configuration->AccountKey(R"(MyAccountKey)");
40+
```
41+
42+
[!INCLUDE [Access Tokens](../../../includes/spatial-anchors-create-locate-anchors-access-tokens.md)]
43+
44+
```cpp
45+
auto configuration = cloudSession_->Configuration();
46+
configuration->AccessToken(R"(MyAccessToken)");
47+
```
48+
49+
[!INCLUDE [Access Tokens Event](../../../includes/spatial-anchors-create-locate-anchors-access-tokens-event.md)]
50+
51+
```cpp
52+
auto accessTokenRequiredToken = cloudSession_->AccessTokenRequired([](auto&&, auto&& args) {
53+
args->AccessToken(R"(MyAccessToken)");
54+
});
55+
```
56+
57+
[!INCLUDE [Asynchronous Tokens](../../../includes/spatial-anchors-create-locate-anchors-asynchronous-tokens.md)]
58+
59+
```cpp
60+
auto accessTokenRequiredToken = cloudSession_->TokenRequired([this](auto&&, auto&& args) {
61+
std::shared_ptr<CloudSpatialAnchorSessionDeferral> deferral = args->GetDeferral();
62+
MyGetTokenAsync([&deferral, &args](std::string const& myToken) {
63+
if (myToken != nullptr) args->AccessToken(myToken);
64+
deferral->Complete();
65+
});
66+
});
67+
```
68+
69+
[!INCLUDE [AAD Tokens](../../../includes/spatial-anchors-create-locate-anchors-aad-tokens.md)]
70+
71+
```cpp
72+
auto configuration = cloudSession_->Configuration();
73+
configuration->AuthenticationToken(R"(MyAuthenticationToken)");
74+
```
75+
76+
[!INCLUDE [AAD Tokens Event](../../../includes/spatial-anchors-create-locate-anchors-aad-tokens-event.md)]
77+
78+
```cpp
79+
auto accessTokenRequiredToken = cloudSession_->AccessTokenRequired([](auto&&, auto&& args) {
80+
args->AuthenticationToken(R"(MyAuthenticationToken)");
81+
});
82+
```
83+
84+
[!INCLUDE [Asynchronous Tokens](../../../includes/spatial-anchors-create-locate-anchors-asynchronous-tokens.md)]
85+
86+
```cpp
87+
auto accessTokenRequiredToken = cloudSession_->TokenRequired([this](auto&&, auto&& args) {
88+
std::shared_ptr<CloudSpatialAnchorSessionDeferral> deferral = args->GetDeferral();
89+
MyGetTokenAsync([&deferral, &args](std::string const& myToken) {
90+
if (myToken != nullptr) args->AuthenticationToken(myToken);
91+
deferral->Complete();
92+
});
93+
});
94+
```
95+
96+
[!INCLUDE [Setup](../../../includes/spatial-anchors-create-locate-anchors-setup-non-ios.md)]
97+
98+
```cpp
99+
cloudSession_->Session(ar_session_);
100+
cloudSession_->Start();
101+
```
102+
103+
[!INCLUDE [Frames](../../../includes/spatial-anchors-create-locate-anchors-frames.md)]
104+
105+
```cpp
106+
cloudSession_->ProcessFrame(ar_frame_);
107+
```
108+
109+
[!INCLUDE [Feedback](../../../includes/spatial-anchors-create-locate-anchors-feedback.md)]
110+
111+
```cpp
112+
auto sessionUpdatedToken = cloudSession_->SessionUpdated([this](auto&&, auto&& args) {
113+
auto status = args->Status();
114+
if (status->UserFeedback() == SessionUserFeedback::None) return;
115+
std::ostringstream str;
116+
str << std::fixed << std::setw(2) << std::setprecision(0)
117+
<< R"(Feedback: )" << FeedbackToString(status.UserFeedback()) << R"( -)"
118+
<< R"( Recommend Create=)" << (status->RecommendedForCreateProgress() * 100) << R"(%)";
119+
feedback_ = str.str();
120+
});
121+
```
122+
123+
[!INCLUDE [Creating](../../../includes/spatial-anchors-create-locate-anchors-creating.md)]
124+
125+
```cpp
126+
// Create a local anchor, perhaps by hit-testing and creating an ARAnchor
127+
ArAnchor* localAnchor;
128+
ArHitResultList* hit_result_list = nullptr;
129+
ArHitResultList_create(ar_session_, &hit_result_list);
130+
CHECK(hit_result_list);
131+
ArFrame_hitTest(ar_session_, ar_frame_, 0.5, 0.5, hit_result_list);
132+
int32_t hit_result_list_size = 0;
133+
ArHitResultList_getSize(ar_session_, hit_result_list, &hit_result_list_size);
134+
if (hit_result_list_size == 0) {
135+
ArHitResultList_destroy(hit_result_list);
136+
return;
137+
}
138+
ArHitResult* ar_hit = nullptr;
139+
ArHitResult_create(ar_session_, &ar_hit);
140+
// The hitTest method sorts the resulting list by distance from the camera, increasing
141+
// The first hit result will usually be the most relevant when responding to user input
142+
ArHitResultList_getItem(ar_session_, hit_result_list, 0, ar_hit);
143+
if (ArHitResult_acquireNewAnchor(ar_session_, ar_hit, &localAnchor) != AR_SUCCESS) return;
144+
ArTrackingState tracking_state = AR_TRACKING_STATE_STOPPED;
145+
ArAnchor_getTrackingState(ar_session_, localAnchor, &tracking_state);
146+
if (tracking_state != AR_TRACKING_STATE_TRACKING) {
147+
ArAnchor_release(localAnchor);
148+
ArHitResult_destroy(ar_hit);
149+
return;
150+
}
151+
ArHitResult_destroy(ar_hit);
152+
ar_hit = nullptr;
153+
ArHitResultList_destroy(hit_result_list);
154+
hit_result_list = nullptr;
155+
156+
// If the user is placing some application content in their environment,
157+
// you might show content at this anchor for a while, then save when
158+
// the user confirms placement.
159+
std::shared_ptr<CloudSpatialAnchor> cloudAnchor = std::make_shared<CloudSpatialAnchor>();
160+
cloudAnchor->LocalAnchor(localAnchor);
161+
cloudSession_->CreateAnchorAsync(cloudAnchor, [this, cloudAnchor](Status status) {
162+
std::ostringstream str;
163+
if (status != Status::OK) {
164+
str << "Save Failed: " << std::to_string(static_cast<uint32_t>(status));
165+
feedback_ = str.str();
166+
return;
167+
}
168+
str << R"(Created a cloud anchor with ID=)" << cloudAnchor->Identifier();
169+
feedback_ = str.str();
170+
});
171+
```
172+
173+
[!INCLUDE [Session Status](../../../includes/spatial-anchors-create-locate-anchors-session-status.md)]
174+
175+
```cpp
176+
cloudSession_->GetSessionStatusAsync([this](Status status, const std::shared_ptr<SessionStatus>& value) {
177+
if (status != Status::OK) {
178+
std::ostringstream str;
179+
str << "Session status error: " << std::to_string(static_cast<uint32_t>(status));
180+
feedback_ = str.str();
181+
return;
182+
}
183+
if (value->RecommendedForCreateProgress() < 1.0f) return;
184+
// Issue the creation request ...
185+
});
186+
```
187+
188+
[!INCLUDE [Setting Properties](../../../includes/spatial-anchors-create-locate-anchors-setting-properties.md)]
189+
190+
```cpp
191+
std::shared_ptr<CloudSpatialAnchor> cloudAnchor = std::make_shared<CloudSpatialAnchor>();
192+
cloudAnchor->LocalAnchor(localAnchor);
193+
auto properties = cloudAnchor->AppProperties();
194+
properties->Insert(R"(model-type)", R"(frame)");
195+
properties->Insert(R"(label)", R"(my latest picture)");
196+
cloudSession_->CreateAnchorAsync(cloudAnchor, [this, cloudAnchor](Status status) {
197+
// ...
198+
});
199+
```
200+
201+
[!INCLUDE [Update Anchor Properties](../../../includes/spatial-anchors-create-locate-anchors-updating-properties.md)]
202+
203+
```cpp
204+
std::shared_ptr<CloudSpatialAnchor> anchor = /* locate your anchor */;
205+
auto properties = anchor->AppProperties();
206+
properties->Insert(R"(last-user-access)", R"(just now)");
207+
cloudSession_->UpdateAnchorPropertiesAsync(anchor, [this](Status status) {
208+
if (status != Status::OK) {
209+
std::ostringstream str;
210+
str << "Updating Properties Failed: " << std::to_string(static_cast<uint32_t>(status));
211+
feedback_ = str.str();
212+
}
213+
});
214+
```
215+
216+
[!INCLUDE [Getting Properties](../../../includes/spatial-anchors-create-locate-anchors-getting-properties.md)]
217+
218+
```cpp
219+
cloudSession_->GetAnchorPropertiesAsync(R"(anchorId)", [this](Status status, const std::shared_ptr<CloudSpatialAnchor>& anchor) {
220+
if (status != Status::OK) {
221+
std::ostringstream str;
222+
str << "Getting Properties Failed: " << std::to_string(static_cast<uint32_t>(status));
223+
feedback_ = str.str();
224+
return;
225+
}
226+
if (anchor != nullptr) {
227+
auto properties = anchor->AppProperties();
228+
properties->Lookup(R"(last-user-access)") = R"(just now)";
229+
cloudSession_->UpdateAnchorPropertiesAsync(anchor, [this](Status status) {
230+
// ...
231+
});
232+
}
233+
});
234+
```
235+
236+
[!INCLUDE [Expiration](../../../includes/spatial-anchors-create-locate-anchors-expiration.md)]
237+
238+
```cpp
239+
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
240+
std::chrono::system_clock::time_point oneWeekFromNow = now + std::chrono::hours(7 * 24);
241+
const int64_t oneWeekFromNowUnixEpochTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(oneWeekFromNow.time_since_epoch()).count();
242+
cloudAnchor->Expiration(oneWeekFromNowUnixEpochTimeMs);
243+
```
244+
245+
[!INCLUDE [Locate](../../../includes/spatial-anchors-create-locate-anchors-locating.md)]
246+
247+
```cpp
248+
auto criteria = std::make_shared<AnchorLocateCriteria>();
249+
criteria->Identifiers({ R"(id1)", R"(id2)", R"(id3)" });
250+
auto cloudSpatialAnchorWatcher = cloudSession_->CreateWatcher(criteria);
251+
```
252+
253+
[!INCLUDE [Locate Events](../../../includes/spatial-anchors-create-locate-anchors-locating-events.md)]
254+
255+
```cpp
256+
auto anchorLocatedToken = cloudSession_->AnchorLocated([this](auto&&, auto&& args) {
257+
switch (args->Status()) {
258+
case LocateAnchorStatus::Located: {
259+
std::shared_ptr<CloudSpatialAnchor> foundAnchor = args->Anchor();
260+
// Go add your anchor to the scene...
261+
}
262+
break;
263+
case LocateAnchorStatus::AlreadyTracked:
264+
// This anchor has already been reported and is being tracked
265+
break;
266+
case LocateAnchorStatus::NotLocatedAnchorDoesNotExist:
267+
// The anchor was deleted or never exited in the first place
268+
// Drop it, or show UI to ask user to anchor the content anew
269+
break;
270+
case LocateAnchorStatus::NotLocated:
271+
// The anchor hasn't been found given the location data
272+
// The user might in the wrong location, or maybe more data will help
273+
// Show UI to tell user to keep looking around
274+
break;
275+
}
276+
});
277+
```
278+
279+
[!INCLUDE [Deleting](../../../includes/spatial-anchors-create-locate-anchors-deleting.md)]
280+
281+
```cpp
282+
cloudSession_->DeleteAnchorAsync(cloudAnchor, [this](Status status) {
283+
// Perform any processing you may want when delete finishes
284+
});
285+
```
286+
287+
[!INCLUDE [Stopping](../../../includes/spatial-anchors-create-locate-anchors-stopping.md)]
288+
289+
```cpp
290+
cloudSession_->Stop();
291+
```
292+
293+
[!INCLUDE [Resetting](../../../includes/spatial-anchors-create-locate-anchors-resetting.md)]
294+
295+
```cpp
296+
cloudSession_->Reset();
297+
```
298+
299+
[!INCLUDE [Cleanup](../../../includes/spatial-anchors-create-locate-anchors-cleanup-others.md)]
300+
301+
```cpp
302+
cloudSession_ = nullptr;
303+
```
304+
305+
[!INCLUDE [Next Steps](../../../includes/spatial-anchors-create-locate-anchors-next-steps.md)]

0 commit comments

Comments
 (0)