Cloud Anchors Developer Guide for iOS

Explore how the iOS sample app uses the Cloud Anchors API and learn about working with the API in your own apps.

If you are new to the Cloud Anchors API, see the Quickstart first for system requirements, setup, and installation instructions.

Explore the sample app

Walk through the sample app to learn about critical tasks for working with cloud anchors.

Session setup

The sample app performs the following important tasks as part of setting up the session:

Passing ARFrames to the GARSession

Make sure that your app passes ARFrames continuously to theGARSession.

To do this, use the following push pattern:

-(void)someSetupMethod {
        arSession.delegate = self;
        garSession.delegate = self;
}

-(void)session:(ARSession *)arSession didUpdateFrame:(ARFrame *)arFrame {
        GARFrame *garFrame = [garSession update:arFrame];
        // … process the frame (optional)
}

You should pass at least one ARFrame to the GARSession before you try to host or resolve anchors. This allows time for the GARSession to be synced with the ARSession.

To learn more about best practices for world tracking in ARKit, see About Augmented Reality and ARKit in Apple's developer documentation.

If you are using Metal or otherwise need a polling solution, see the Optional polling pattern in this guide.

Hosting and resolving anchors

The Cloud Anchors API provides methods for cloud anchor hosting and resolving. The API also includes delegate methods to provide the result of completed host and resolve requests.

Hosting anchors

Hosting an ARAnchor maps it in a common coordinate system for a given physical space.

A host request sends visual mapping data to a Google server to map the ARAnchor’s position in a coordinate system representing the current physical space. A successful host request returns a hosted GARAnchor that has been assigned a cloud anchor ID.

- (void)addAnchorWithTransform:(matrix_float4x4)transform {
  self.arAnchor = [[ARAnchor alloc] initWithTransform:transform];
  [self.sceneView.session addAnchor:self.arAnchor];
  self.garAnchor = [self.gSession hostCloudAnchor:self.arAnchor error:nil];
  [self enterState:HelloARStateHosting];
}

Resolving anchors

Resolving a cloud anchor lets Android and iOS devices in a given physical space add its previously hosted anchors to their scene.

An anchor resolve request sends a cloud anchor ID with visual feature descriptions from the current frame to a Google server. The server attempts to match these visual feature descriptions against its understanding of where currently hosted cloud anchors are mapped.

A successful resolve request returns a GARAnchor that has a valid transform and cloud anchor ID. The sample app adds the successfully resolved GARAnchor to the session.

- (void)resolveAnchorWithIdentifier:(NSString *)identifier {
  self.garAnchor = [self.gSession resolveCloudAnchorWithIdentifier:identifier error:nil];
}

Delegate methods for host and resolve requests

Host and resolve methods have GARSessionDelegate methods to provide callbacks on request success and failure.

Host

  • session:didHostAnchor:
  • session:didFailToHostAnchor:

Resolve

  • session:didResolveAnchor:
  • session:didFailToResolveAnchor:

-(void)session:(ARSession *)arSession didUpdateFrame:(ARFrame *)arFrame {
  [...]

-(void)session:(GARSession *)garSession didHostAnchor:(GARAnchor *)garAnchor {
        // successful host
}

-(void)session:(GARSession *)garSession didFailToHostAnchor:(GARAnchor *)garAnchor {
        // failed host
}

-(void)session:(GARSession *)garSession didResolveAnchor:(GARAnchor *)garAnchor {
        // successful resolve
}

-(void)session:(GARSession *)garSession didFailToResolveAnchor:(GARAnchor *)garAnchor {
        // failed resolve
}

API quotas

The ARCore Cloud Anchor API has the following quotas for request bandwidth:

Quota type Maximum Duration Applies to
Number of anchors Unlimited N/A Project
Anchor host requests 30 minute IP address and project
Anchor resolve requests 300 minute IP address and project

Best practices

The following best practices help create a good cloud anchors user experience.

General

  • Avoid hosting or resolving cloud anchors on flat, shiny surfaces.

    • For best results, avoid reflective surfaces or surfaces without visual features, such as a blank, smooth, white wall.
  • Make sure that the lighting in the room is sufficient.

  • For best results, lighting conditions should be consistent between anchor host and resolve requests.
  • Pass ARFrames to your GARSession before you try to host or resolve anchors.

Hosting

Before hosting an anchor:

  • Try to look at the anchor from different angles.
  • Move around the anchor for at least a few seconds.
  • Make sure you are not too far away from the anchor.

Resolving

When resolving an anchor:

  • Make sure you are close to where the anchor was hosted.
    • If you are too far away from a cloud anchor’s position, it might resolve incorrectly.
  • A cloud anchor might resolve incorrectly if your phone camera is pointed at a space that is different from but visually similar to where the cloud anchor was hosted.

Known issues and workarounds

Default scheme settings cause intermittent app crash

GPU Frame Capture and Metal API Validation scheme settings are enabled by default. This can sometimes cause the app to crash within the SDK.

How to diagnose

  1. Take a look at your stack trace if a crash occurs.
  2. If you see MTLDebugComputeCommandEncoder in the stack trace, it is likely due to the default scheme settings. Try the following workaround.

Workaround

  1. Go to Product > Scheme > Edit scheme…
  2. Open the Run tab.
  3. Click Options to view current settings.
  4. Make sure that GPU Frame Capture and Metal API Validation are disabled.
  5. Close the scheme configuration menu.
  6. Build and run the app again.

For additional known issues, see the CHANGELOG in Cocoapods.

Limitations

Optional GARSession polling pattern

Use the following pattern to pass ARFrames to the GARSession if both of the following apply to your project:

  • You are using Metal or need a polling option for another reason
  • Your app runs at a minimum 30 fps (required)
-(void)myOwnPersonalUpdateMethod {
        ARFrame *arFrame = arSession.currentFrame;
        GARFrame *garFrame = [garSession update:arFrame];
        // your update code here
}

Next steps

Send feedback about...