이전 ARCore Cloud Anchor API는 지원 중단되었으며 2023년 8월 31일 이후에는 지원되지 않습니다. 앱에서 이 API를 사용하는 경우 최대한 빨리 새로운 ARCore API 엔드포인트를 사용하도록 업데이트해야 합니다.

iOS용 Cloud Anchors 개발자 가이드

iOS용 ARCore SDK는 ARKit과 연결되어 클라우드 앵커 기능을 제공하므로 동일한 환경에서 iOS와 Android 기기 간에 앵커를 공유할 수 있습니다.

내 앱에서 ARCore API 또는 ARCore 클라우드 앵커 서비스를 사용하는 방법을 알아보세요. 클라우드 앵커를 처음 사용하는 경우 다음 안내를 따르세요.

앱에서 클라우드 앵커 사용 설정

Cloud Anchors API를 사용하려면 iOS에서 ARCore 세션 구성에 설명된 대로 GARSessionConfiguration를 만들고 cloudAnchorMode 속성을 설정해야 합니다. setConfiguration:error: (GARSession)를 사용하여 구성을 설정합니다.

또한 Google Cloud Platform 프로젝트에 ARCore API를 사용 설정해야 합니다.

앵커 호스팅 및 확인

ARCore API를 사용하여 클라우드 앵커를 호스팅하고 확인할 수 있습니다. API에는 완료된 요청에 콜백을 제공하는 대리자 메서드도 포함됩니다.

앵커 호스팅

ARAnchor을 호스팅하면 특정 물리적 공간의 공통 좌표계에 앵커가 배치됩니다.

호스트 요청은 현재 물리적 공간을 나타내는 좌표계에서 ARAnchor의 위치를 매핑하는 시각적 데이터를 Google 서버로 전송합니다. 이 요청은 ID가 없는 GARAnchor를 반환합니다. 호스트 요청이 성공하면 반환된 GARAnchor에 이후 GARFrame의 고유 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];
}

앵커 확인

ARAnchor를 확인하면 주어진 물리적 공간에 있는 Android 및 iOS 기기가 새 장면에 이전에 호스팅된 앵커를 추가할 수 있습니다.

확인 요청은 Google 프레임에 현재 프레임의 시각적 데이터와 함께 클라우드 앵커 ID를 전송합니다. 이 요청은 유효한 변환 또는 클라우드 앵커 ID 없이 GARAnchor를 반환합니다. 서버는 이 시각적 데이터를 현재 호스팅된 클라우드 앵커가 매핑된 이미지와 일치시키려고 시도합니다. 호스트 요청에 성공하면 GARanchor에 이후 GARFrame에서 유효한 변환과 고유 ID가 할당됩니다.

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

// Pass the ARFRame to the ARCore session every time there is a frame update.
// This returns a GARFrame that contains a list of updated anchors. If your
// anchor's pose or tracking state changed, your anchor will be on the list.
- (void)cloudAnchorManager:(CloudAnchorManager *)manager didUpdateFrame:(GARFrame *)garFrame {
  for (GARAnchor *garAnchor in garFrame.updatedAnchors) {
    if ([garAnchor isEqual:self.garAnchor] && self.resolvedAnchorNode) {
      self.resolvedAnchorNode.simdTransform = garAnchor.transform;
      self.resolvedAnchorNode.hidden = !garAnchor.hasValidTransform;
    }
  }
}

호스트 및 확인 요청을 위한 메서드 위임

호스트 및 확인 요청에는 요청 성공 및 실패 시 콜백을 제공하는 GARSessionDelegate 메서드가 있습니다.

호스트

  • session:didHostAnchor:
  • session:didFailToHostAnchor:

해결

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

GARSession 폴링 패턴(선택사항)

Metal을 사용하거나 폴링 옵션이 필요한 경우 또한 앱이 최소 30fps에서 실행되면 다음 패턴을 사용하여 ARFrameGARSession에 전달합니다.

-(void)myOwnPersonalUpdateMethod {
        ARFrame *arFrame = arSession.currentFrame;
        NSError *error = nil;
        GARFrame *garFrame = [garSession update:arFrame error:&error];
        // your update code here
}

지속성이 있는 클라우드 앵커 호스팅

ARCore v1.20 이전에는 클라우드 앵커를 처음 호스팅한 후 최대 24시간 동안만 확인할 수 있었습니다. 영구 클라우드 앵커를 사용하면 이제 hostCloudAnchor:error:를 사용하여 TTL(수명)을 1~365일로 설정하여 클라우드 앵커를 만들 수 있습니다. 또한 Cloud Anchor Management API를 사용하여 이미 호스팅된 후 앵커의 전체 기간을 연장할 수 있습니다.

/**
* This creates a new Cloud Anchor with a given lifetime in days, using the transform
 * of the provided anchor.
 *
 * The cloud state of the returned anchor will be set to GARCloudAnchorStateTaskInProgress and the
 * initial transform will be set to the transform of the provided anchor. However, the returned
 * anchor and the original anchor are independent of one another, and their two transforms
 * may diverge over time.
 *
 * Hosting requires a working Internet connection and an active session where the tracking state
 * is ARTrackingStateNormal. If it is unable to establish a connection to the ARCore Cloud Anchor
 * service, ARCore will continue to silently retry in the background.
 *
 * @param anchor The ARAnchor with the desired transform to be used to create a hosted Cloud
 *     Anchor.
 * @param TTLDays The anchor’s lifetime in days. Must be a positive number. The maximum
 * allowed value is 1 if you are using an API key to authorize the Cloud Anchor API call.
 * Otherwise, the maximum allowed value is 365.
 * @param error Out parameter for an NSError. Possible errors include:
 *     GARSessionErrorCodeInvalidArgument - Invalid (nil) anchor or invalid TTL.
 *     GARSessionErrorCodeNotTracking - Bad current ARTrackingState.
 *     GARSessionErrorCodeResourceExhausted - ARCore tried to create too many Cloud Anchors.
 * @return The new GARAnchor, or nil if there is an error.
 */

- (GARAnchor *_Nullable)hostCloudAnchor:(ARAnchor *)anchor
                                TTLDays:(NSInteger)TTLDays
                                  error:(NSError **)error;

승인

Cloud Anchors API를 사용하려면 앱이 승인을 받아야 합니다. 서명된 JSON 웹 토큰 (JWT) 또는 API 키 승인을 사용할 수 있습니다.

토큰 (서명된 JWT) 승인

서명된 JSON 웹 토큰 (JWT) 승인을 사용하여 클라우드 앵커를 최대 365일 동안 호스팅합니다. API 키 승인을 사용하여 클라우드 앵커를 최대 하루 동안 호스팅합니다.

현재 유일하게 지원되는 토큰 유형은 서명된 JWT입니다 (즉, Google 서비스 계정으로 서명된 JSON 웹 토큰). JWT에 대한 소개는 공식 JWT 웹사이트를 참조하세요. iOS용 JSON 웹 토큰을 생성하려면 서버에 다음 요구사항을 충족하는 엔드포인트가 있어야 합니다.

  • 자체 승인 메커니즘이 엔드포인트를 보호해야 합니다.

  • 엔드포인트에서 매번 다음과 같은 새 토큰을 생성해야 합니다.

    • 각 사용자에게 고유한 토큰이 제공됩니다.
    • 토큰은 즉시 만료되지 않습니다.

서비스 계정 및 서명 키 만들기

Google 서비스 계정 및 서명 키를 만들려면 다음 단계를 따르세요.

  1. Google Cloud Platform Console의 탐색 메뉴에서 APIs & Services > Credentials로 이동합니다.

  2. 원하는 프로젝트를 선택하고 Create Credentials > Service account를 클릭합니다.

  3. Service account details에서 새 계정의 이름을 입력하고 Create를 클릭합니다.

  4. Service account permissions 페이지에서 Select a role 드롭다운으로 이동합니다. Service Accounts > Service Account Token Creator를 선택한 다음 Continue를 클릭합니다.

  5. Grant users access to this service account 페이지에서 Done을 클릭합니다. APIs & Services > Credentials 페이지로 돌아갑니다.

  6. Credentials 페이지에서 Service Accounts 섹션까지 아래로 스크롤하고 방금 만든 계정의 이름을 클릭합니다.

  7. Service account details 페이지에서 Keys 섹션까지 아래로 스크롤하고 Add Key > Create new key를 선택합니다.

  8. 키 유형으로 JSON를 선택하고 Create을 클릭합니다. 그러면 비공개 키가 포함된 JSON 파일이 머신에 다운로드됩니다. 다운로드한 JSON 키 파일을 안전한 위치에 저장합니다.

서버에서 토큰 만들기

서버에 새 토큰 (JWT)을 만들려면 표준 JWT 라이브러리와 새 서비스 계정에서 안전하게 다운로드한 JSON 파일을 사용합니다.

개발 머신에서 토큰 만들기

개발 머신에서 JWT를 생성하려면 다음 oauth2l 명령어를 사용합니다.

oauth2l fetch --jwt --json $KEYFILE $AUDIENCE --cache ""

매번 다른 토큰이 생성되도록 하려면 --cache 플래그를 사용하여 빈 캐시 위치를 지정해야 합니다. 추가 공백 또는 줄바꿈 문자로 인해 ARCore에서 토큰을 거부하므로 결과 문자열을 잘라내야 합니다.

토큰 서명

JWT 알고리즘에 서명하려면 RS256 알고리즘과 다음 클레임을 사용해야 합니다.

  • iss: 서비스 계정 이메일 주소입니다.
  • sub: 서비스 계정 이메일 주소입니다.
  • iat — 토큰이 생성된 Unix 시간(초)입니다.
  • exp~iat + 3600(1시간). 토큰이 만료되는 Unix 시간(초)입니다.
  • aud — 잠재고객입니다. ARCore API의 올바른 '잠재고객'은 https://arcore.googleapis.com/입니다.

비표준 클레임은 JWT 페이로드에 필요하지 않지만 해당 사용자를 식별하는 데 유용한 uid 클레임을 찾을 수 있습니다.

JWT를 생성하는 데 다른 접근 방식(예: Google 관리 환경에서 Google API 사용)을 사용하는 경우 이 섹션의 클레임으로 JWT에 서명해야 합니다. 무엇보다도 잠재고객이 올바른지 확인해야 합니다.

ARCore 세션에 토큰 전달

먼저 sessionWithError:를 사용하여 세션을 구성합니다.

NSError *error = nil;
GARSession *session = [GARSession sessionWithError:&error];

토큰을 받으면 setAuthToken:를 사용하여 세션에 전달합니다.

/**
 * Provide an auth token to authorize your app to use the ARCore Cloud Anchor API. If
 * you used an API key to create the session, ARCore will ignore the token and log an error.
 * Otherwise, it will use the most recent valid auth token that you passed in. Call this
 * method each time you refresh your token.
 *
 * @param authToken The token to use when authorizing your call to the ARCore Cloud Anchor API. This
 *                  must be a nonempty ASCII string with no spaces or control characters. ARCore
 *                  will use this until you pass in another token. Currently, JWTs are the only
 *                  supported token types.
 */
- (void)setAuthToken:(NSString *)authToken;

토큰을 세션에 전달할 때 다음 사항에 유의하세요.

  • 앵커를 호스팅하거나 결정하려고 시도하기 전에 유효한 토큰을 전달하지 않으면 승인 오류가 발생합니다.

  • ARCore에서는 공백이나 특수문자가 포함된 토큰을 무시합니다. 또한 ARCore는 유효한 API 키로 세션을 만드는 경우 모든 토큰을 무시합니다. 이전에 API 키를 사용했지만 더 이상 필요하지 않은 경우 Google Developers Console에서 삭제하고 사용자를 최신 버전으로 마이그레이션한 후 앱에서 삭제하는 것이 좋습니다.

  • 토큰은 일반적으로 1시간 후에 만료됩니다. 토큰이 사용 중에 만료될 가능성이 있다면 새 토큰을 가져와서 API에 전달합니다.

API 키 승인

API 키 승인 옵션을 사용하여 클라우드 앵커를 최대 하루 동안 호스팅합니다.

API 키를 가져와 프로젝트에 추가하려면 다음 단계를 따르세요.

  1. API 키를 가져오는 방법은 Google Cloud Platform Console 고객센터를 참고하세요.

  2. Xcode에서 새 API 키를 sessionWithAPIKey:bundleIdentifier:error:에 전달하여 프로젝트에 추가합니다.

    NSError *error = nil;
    GARSession *session = [GARSession sessionWithAPIKey:@"your-api-key" bundleIdentifier:nil error:&error];
    

매핑 품질

매핑 품질 API는 이전 몇 초 동안 ARCore에서 보고 제공된 카메라 변환에서 볼 수 있는 시각적 특징 지점의 품질을 추정합니다. 고품질 기능을 사용하여 클라우드 앵커를 호스팅하면 일반적으로 클라우드 앵커 변환이 더 쉽고 정확하게 해결됩니다. 지정된 변환에 대한 특성 지도 품질을 추정할 수 없는 경우 ARCore는 경고 메시지를 기록하고 GARFeatureMapQualityInsufficient를 반환합니다. 이 상태는 ARCore가 클라우드 앵커 확인에 더 많은 어려움이 있을 수 있음을 나타냅니다. 호스팅하려는 클라우드 앵커의 원하는 위치를 다양한 각도에서 볼 수 있도록 사용자에게 기기를 이동하도록 권장합니다.

/**
 * @param transform The camera transform to use to estimate the mapping quality.
 * @param error Out parameter for an `NSError`. Possible errors:
 *        GARSessionErrorCodeNotTracking - Bad current ARTrackingState.
 * @return The estimated quality of the visual feature points seen
 *        by ARCore in the preceding few seconds and visible from the provided camera
 *        transform.
 */

- (GARFeatureMapQuality)estimateFeatureMapQualityForHosting:(simd_float4x4)transform
                                                      error:(NSError **)error;

API 할당량

ARCore API에는 요청 대역폭에 대한 다음과 같은 할당량이 있습니다.

할당량 유형 최대 길이 적용 대상
앵커 수 무제한 N/A 프로젝트
앵커 호스트 요청 30 IP 주소 및 프로젝트
앵커 확인 요청 300 IP 주소 및 프로젝트

알려진 문제 및 해결 방법

iOS용 ARCore SDK 작업 시 알려진 문제가 몇 가지 있습니다.

기본 스키마 설정으로 인해 앱이 간헐적으로 비정상 종료됨

GPU 프레임 캡처 및 Metal API 유효성 검사 스키마 설정은 기본적으로 사용 설정되어 있으므로 SDK로 인해 앱이 비정상 종료될 수 있습니다.

앱 비정상 종료 진단

비정상 종료가 발생한 것으로 의심될 때마다 스택 트레이스를 살펴보세요. 스택 트레이스에 MTLDebugComputeCommandEncoder가 표시된다면 기본 스키마 설정 때문일 수 있습니다.

해결 방법

  1. Product > Scheme > Edit Scheme… 페이지로 이동합니다.

  2. Run 탭을 엽니다.

  3. Options를 클릭하여 현재 설정을 확인합니다.

  4. GPU Frame CaptureMetal API Validation가 모두 사용 중지되어 있는지 확인합니다.

  5. 앱을 빌드하고 실행합니다.

추가로 알려진 문제는 CocoaPods CHANGELOG를 참고하세요.

제한사항

iOS용 ARCore SDK는 ARKit setWorldOrigin(relativeTransform:) 메서드 호출을 지원하지 않습니다.

성능에 대한 고려사항

ARCore API를 사용 설정하면 메모리 사용량이 증가합니다. 네트워크 사용량과 CPU 사용률이 높기 때문에 기기의 배터리 사용량이 증가할 수 있습니다.

다음 단계