The concept of an Anchor in ARCore is very simple. An Anchor defines a certain location (a pose) in 3D space that can be used for placing objects. The Anchor keeps the 3D object in place (like an anchor hold a ship in place).
Google defines an Anchor like this:
"A fundamental concept in ARCore is that of an Anchor, which describes an approximation of a fixed location and orientation in the real world.
Anchor poses are automatically adjusted by ARCore as its understanding of the environment improves based on the device's motion."
A Cloud Anchor is a new type of Anchor, where the information of the position and pose togehter with some information on the phyiscal surroundings of that Anchor are uploaded to the ARCore Cloud Anchor Service. This is called hosting the Anchor. When the Anchor is hosted, it is assigned an unique ID, the cloud anchor ID. This ID then can be shared between different applications. Each application that gets the anchor ID can now try to resolve the Cloud Anchor and will then see the same 3D model that another application has shared in space. So here are the single steps again:
Because Cloud Anchors uses a cloud service, your app must have permission to access the internet. This is done by adding the following line to the AndroidManifest.xml
:
<uses-permission android:name="android.permission.INTERNET"/>
To use cloud anchors, you’ll need to add a Google ARCore Cloud Anchors API Key to your app. The following steps are required for this:
AndroidManifest.xml
file as follows:<meta-data
android:name="com.google.android.ar.API_KEY"
android:value="<YOUR_API_KEY>"/>
In order to be able to create Cloud Anchors the ARCore Session needs to be configured for this in your app. You have learned how to create a Config for using the AugmentedImageDatabase in the last assigment. This is basically the same thing but for Cloud Anchors. Somewhere in your app (where it makes sense) add the following code:
Config config = new Config(session);
config.setCloudAnchorMode(Config.CloudAnchorMode.ENABLED);
session.configure(config);
To create a hosted Cloud Anchor, all you need to do is to create a normal Anchor for example, like you did before in the assignment using the HitResult when the user taps on a plane:
Anchor anchor = hitResult.createAnchor();
To create a hosted Cloud Anchor add this line below:
// Create a hosted anchor from a standard anchor.
Anchor newAnchor = session.hostCloudAnchor(anchor);
The hostCloudAnchor() method schedules a background task that will begin the hosting process, but the method call returns immediately, so the app’s UI thread is not blocked. You can check to see if the anchor was successfully hosted or not by polling the state of the anchor after every session.update() call.
In order to do this, you better store your new Anchor in a member variable to access this later in the onUpdateFrame()
handler.
As soon as the upload of the Anchor to the ARCore Cloud Anchor Service was successful, you can retrieve the Cloud Anchor ID. Unfortunately there is no callback interface that allows to get called when the upload was successful. Thus you will need to poll, for example in your onUpdateFrame()
handler.
Anchor.CloudAnchorState cloudState = newAnchor.getCloudAnchorState();
if (cloudState.isError()) {
// something went wrong with the upload
} else if (cloudState == Anchor.CloudAnchorState.SUCCESS) {
//Anchor hosted successfully, you can retrieve the ID now like this:
String id = newAnchor.getCloudAnchorId());
}
When you have a Cloud Anchor ID you can store it (for example in teh SharedPreferences) in your app to reload it later or transfer it to another user’s app, so he/she can resolve the Cloud Anchor using the ID.
Resolving the Cloud Anchor from the ID is very simply done by calling this:
Anchor resolvedAnchor = session.resolveCloudAnchor(cloudAnchorId);
This will start a process of downloading the Cloud Anchor information in the background.
Like when uploading a Cloud Anchor to the ARCore Cloud Anchor Service, this time you also need to poll to find out if the download is successful and the Anchor was resolved.
Do this, for example, in your onUpdateFrame()
handler method.
Anchor.CloudAnchorState cloudState = anchor.getCloudAnchorState();
if (cloudState.isError()) {
// Error resolving anchor
} else if (cloudState == Anchor.CloudAnchorState.SUCCESS) {
// Anchor resolved successfully
}
The full potential of Cloud Anchors is only unlocked when you can share the cloud anchor IDs between different devices.
The mechanism of sharing the cloud anchor IDs is up to the app developer and anything can be used to transfer the string from one device to another.
One easy way is to use the Firebase Realtime Database to transfer anchor IDs between instances of the app.
For information how to use the Firebase Realtime Database, please refer to the Firebase Documentation.
The use of Cloud Anchors is a good way to create interactive Multiuser AR Applications, where people in the same room can interact in a with virtual objects in reality. Google has experimented with the Cloud Anchor API an developed different prototype apps. Take a look at this video to get some inspiration on what you can do with this. Multiuser AR apps (shared augmentations) start from minute 14.
Have fun!