【Swift】WWDC2022 で日本対応された LocationAnchors を触ってみる

## LocationAnchorsとは
元々は WWDC2020のARKit4が出たタイミングで発表されたサービスで位置情報とAR技術と画像認識を組み合わせ、高精度の位置、高度にARオブジェクトを配置することができます。
[WWDC2022セッション動画 「Explore ARKit 4」](https://developer.apple.com/videos/play/wwdc2020/10611)

しかし、当時の状況ではまだ日本の都市が対応していなかったため、動作確認ができない状況でした。

それが、WWDC2022で下記の都市も対応されたため、使ってみようと思います。
- 東京
- 横浜
- 大阪
- 名古屋
- 京都
- 広島
- 福岡

対応地域の詳細はAppleのドキュメント参照。
https://developer.apple.com/documentation/arkit/argeotrackingconfiguration

## 本記事の概要
今回はAppleから出しているLocation Anchorsのデモアプリを確認し、ARオブジェクトを置くまでの挙動を記事にまとめて整理したいと思います。
デモアプリは下記からダウンロードできます。
https://developer.apple.com/documentation/arkit/content_anchors/tracking_geographic_locations_in_ar


## 起動時
### デバイスの対応確認
AppDelegete内でARGeoTrackingConfigurationクラスの[isSupported](https://developer.apple.com/documentation/arkit/arconfiguration/2923553-issupported)プロパティを用いて対応したデバイスか判定している。

```swift
if !ARGeoTrackingConfiguration.isSupported {
    // サポートしていない時の処理
}
```
このデモアプリでは、対応していなデバイスはその旨を表示した画面を表示している。

### ARCoachingOverlayViewの初期設定
- ARCoachingOverlayViewとは
  - ARKitがトラッキングを確立するため、標準化された案内を行い、ユーザーにデバイスを動かしてもらうよう促す。（[リファレンス](https://developer.apple.com/documentation/arkit/arcoachingoverlayview)）


```swift
let coachingOverlay = ARCoachingOverlayView()
// 省略
coachingOverlay.goal = .geoTracking
coachingOverlay.session = arView.session
```

ARCoachingOverlayVieのgoalには正確な地理情報を取得するよう[geoTracking](https://developer.apple.com/documentation/arkit/arcoachingoverlayview/goal/geotracking)を指定
コーチングを行うセッションは、Storyboardに設定されているARViewを指定

### Delegate設定
LocationManagerとMapKitのDelegateを設定

### ARのセッション管理
対応地域確認後にセッションを開始するため、この時点では[automaticallyConfigureSession](https://developer.apple.com/documentation/realitykit/arview/automaticallyconfiguresession)プロパティをFalseに設定し、セッションの自動構成を停止する。

```swift
// Disable automatic configuration and set up geotracking
arView.automaticallyConfigureSession = false
```

#### 対応地域の確認
ARGeoTrackingConfigurationクラスの[checkAvailability(completionHandler:)](https://developer.apple.com/documentation/arkit/argeotrackingconfiguration/3571351-checkavailability)メソッドを使用して、現在地が対応しているか確認する。
特に位置情報の引数とか、LocationMangerのユーザー許可は取ってないが、このメソッドで現在地が対応しているか判断ができる。

```swift
// Check geo-tracking location-based availability.
ARGeoTrackingConfiguration.checkAvailability { (available, error) in
    if !available {
        // 対応地域ではない時の処理
    }
}
```


また、現在地ではなく特定の位置が対応しているか確認したい場合はそれ用のメソッドもある。（[checkAvailability(at:completionHandler:)](https://developer.apple.com/documentation/arkit/argeotrackingconfiguration/3571350-checkavailability)）


#### ARGeoTrackingConfigurationの設定
平面検出の方法の設定、セッションの開始
```swift
let geoTrackingConfig = ARGeoTrackingConfiguration()
geoTrackingConfig.planeDetection = [.horizontal] // 垂直方向を指定
arView.session.run(geoTrackingConfig, options: .removeExistingAnchors)
```


## ARセッション開始
### ジオトラッキングのセッション状態の変更
[session(_:didChange:)](https://developer.apple.com/documentation/arkit/arsessionobserver/3580878-session)メソッドで、カメラからの画像収集データが十分かどうか判断する。

データの収集状態は[ARGeoTrackingStatus.State](https://developer.apple.com/documentation/arkit/argeotrackingstatus/state)を参照。
収集済み以外のステータスが取れた際の、理由については[ARGeoTrackingStatus.StateReason](https://developer.apple.com/documentation/arkit/argeotrackingstatus/statereason)プロパティに格納される。

```swift
func session(_ session: ARSession, didChange geoTrackingStatus: ARGeoTrackingStatus) {
        if geoTrackingStatus.state == .localized {
            // 現在地情報のデータが十分に集まった
        } else {
            // まだ収集中
            switch geoTrackingStatus.stateReason {
            case .none:
                // 事由なし（引き続き画像データの取得を行う)
                break
            case .worldTrackingUnstable:
                //動作が不安定
            }
        }
    }
```

### オブジェクトの配置
[ARGeoAnchor](https://developer.apple.com/documentation/arkit/argeoanchor)のインスタンスを生成する。

```swift
var geoAnchor: ARGeoAnchor!
geoAnchor = ARGeoAnchor(coordinate: location, altitude: altitude)
```

引数で指定した座標と高度でAnchorを作成し、ARViewに追加する。

## 最後に
ARオブジェクト配置まで見てきましたが、実際に自分のiPhoneでもARオブジェクトが配置されていることを確認できました。
なかなかLocation Anchorsに関する記事がないため、書いてみましたが、いろんな技術に触ってみるのもいいですね。

これから、地元のビル街にお魚いっぱい置いて水族館にでもしようと思います。