AR 기능을 쓰는 흐름에는 크게 3가지가 있다.
AR이 앱의 주요한 기능인 경우, AR이 앱의 부차적인 기능인 경우, AR을 이용해 사용자의 얼굴을 인식하는 경우.
첫 번째
경우 back카메라의 사용권한이 있어야하기 때문에 inpo.plist의 UIRequiredDeviceCapabilities
섹션에 arkit key
를 추가한다.
두 번째
경우 해당 기기의 isSupported 속성을 확인해야한다. (ARConfiguration subclass의 속성)
세번째
Face trackcing의 경우 font-facing TrueDepty카메라(iphone X)가 필요하기 때문에 반드시 ARFaceTrakingConfiguration.isSupported속성을 이용해 해당기기가 가능한지 확인해야한다.
무엇이 되었건 ARKit를 사용하려면 사용자에게 카메라 사용권한을 받아야한다. ARKit는 따로 기능을 지정하지 않아도 자동으로 유저에게 AR session을 실행하는 경우 권한을 요청한다.
ARKit Xcode 템플릿으로 앱 제작 시작하는 경우 기본적인 카메라 사용 description이 제공된다
(=Info.plist에 NSCameraUsageDescription 키가 추가되어있다. .)
World-tracking AR session은 visual-inertial odometry라는 기술을 사용한다. 이 기술은 ARCamera transform으로 표현되는 모션센서를 통한 데이터(기기의 위치, 방향에 대한 정보. pose라고도 불림)를 이용한다. 결국 카메라를 이용한 비주얼적인 정보와(visual complexity or recognizable features) 지속적인 센서데이터가 필요하다는 것.
이러한 변화는 ARSessionObserver
델리게이트 메서드와 ARCamera
라는 속성을 이용해 변화를 tracking할 수 있다.
Session의 흐름
ARCamera.TrackingState.notAvailable
ARCamera.TrackingState.limited(_:)
: 기기의 위치(pose) 가능하지만(= 모션센서로 데이터 얻는것 가능) 정확도에 대해선 확신할 수 없을 때. 해당 상태에선 트래킹 퀄리티가 떨어짐. ARCamera.TrackingState.Reason.initializing 상태로 세션이 존재하게 됨// ARCamera.TrackingState.limited(_:)
case limited(ARCamera.TrackingState.Reason)
// ARCamera.TrackingState.Reason
case initializing
case relocalizing // interruption이후 다시 ARsession시도하려고 할 때
case excessiveMotion // 기기가 너무빨리 움직여서 이미지 기반의 포지션을 트래킹하지 못 할때
case insufficientFeatures // 카메라를 통해 보여지는 화면이 구분할 만큼 충분하지 않을 때
ARCamera.TrakingSTate.normal
: 기기의 pose가 정확하며 모든 ARKit의 기능이 사용가능하다.
Limited에서 normal 상태 사이에 어떤 일이 있는가?
리밋티드 상태인 이유는 두가지. 플레인엥커
를 추가하거나 업데이트하지 않음. Hit-Testing 메소드
를 실행했는데 어떤 결과도 제공하지 않았을 때
기기의 상태에 따라 리밋티드 상태로 언제든지 변경될 수 있다(ex : 빈 벽을 카메라로 비추었을 때, 불빛 비추었을 때 등)
리밋상태에서 이유를 알고싶을 땐 ARCamera.TrackingState.Reason
값으로 알아내 보자!
Interruption 이후 다시 가상 물체를 위치시킬 때 (relocalizing)
sessionShouldAttemptRelocalization(_:)
메소드를 사용해서 relocalization→ 해당 메소드가 true를 반환하며 ARKit는 방해받기 전 유저의 환경에 대한 정보들(지식들)을 가져와가지고 현재 카메라, 센서데이터와 reconcile한다. = 즉 방해 직전 정보 가져와서 현재 정보랑 합친다는 것. 이 과정중에 tracking state는 limited
!(.Reason.relocalizing)
run(:option:)
과 resetTraking
이용) 해야함.이렇게 안하면 절대 다시 물체 트래킹 못함... 명심명심
버전 12 이후부터는 ARWorldMap 클래스가 ARKit가 세션을 다시 resume하기 위해 필요한 정보를 저장해 둔다.
정보를 저장하는 때는 state가 normal
로 변경되었을 때!
클래스를 파일로 저장한 후 interruption이후 다시 relocalization해야하는 경우 등에 사용(앱을 다시 실행하는 경우도 이에 해당한다)
anchors도 포함하고 있기 때문에 이전 session(resume하기 이전 세션)의 가상 컨텐츠와 매칭 할 수 있다.
ARWorldMap에 이전 세션의 가상 컨텐츠에 대한 정보가 있으니 이 클래스를 이용하면 항상 state를 normal로 바꾸는게 성공할까? → NO. 주위 환경의 변화에 영향을 많이 받는다. 만약 이전 세션과 현재 세션의 차이가 크다면 성공적으로 session을 resume 할 수 없다.
앱 종료 후 다시 켰을 때 같은 AR session으로 돌아오고싶으면 어떻게 하면 되나요?
AR session을 다시 실행하도록 하는 이벤트에 world map을 저장한다
여기서 말하는 world map은 가상물체가 위치한 실제세계의 스냅샷 같은 것
주의사항
- 세션이 ARFrame.WorldMappingStatus.mapped상태였거나 세션이 실행되는 동안 단 한번이라도 해당 상태였어야 한다.
initialWorldMap 속성을 이용해서 저장했던 world map을 relocalize한다.
전체적인 흐름 :
세션은 ARCamera.TrakingState.limited(_:) 상태 → ARKit(initialWorldMap)가 world map 과 현재 환경을 reconcile → 상태가 normal로 변경 → 기록된 world map과 세션이 매치되는지 표시해준다.
주의사항
world map
일 수 있도록 유저에게 노티를 줘야한다. (ex : 요기가서 카메라를 가져다 대세요! 안그럼 안나옴! 등등)run(:option:)
과 resetTraking
이용interruption
상태인 이유