🌏

ARCore Geospatial APIをUnityで使ってみる

2022/05/13に公開約5,200字8件のコメント

概要

  • ARCore Geospatial APIとはGoogleの発表したVPS(Visual Positioning Service/System)です
  • ARCoreですが、Android/iOS両方で利用することができます
  • 今回はUnityでのサンプルの動かし方を紹介します

https://developers.google.com/ar/develop/geospatial?hl=ja
https://www.youtube.com/watch?v=PM5rl4z9mto

環境

Unity 2021.3.0f1
AR Fundation 4.2.3
ARCore XR Plugin 4.2.3
ARKit XR Plugin 4.2.3
ARCore Extensions 1.31.0

GCPの設定を行う

  • VPSを利用するためにGCP(Google Cloud Platform)の設定が必要です
  1. プロジェクトの作成
  2. サイドバーで [API とサービス]、[ライブラリ] の順に選択
  3. ARCore API を検索して選択し、[有効にする] をクリックします
  • 次に認証情報を作成します。ドキュメントではAPIキー以外の方法が推奨されていますが、簡単のため今回はAPIキーを利用した方法を紹介します。
  1. APIとサービスから認証情報へ進む

  2. 認証情報を作成でAPIキーを選択

  3. APIキーが作成出来たらどこかにメモっておく

これでGCP側の準備は完了です

Unityの準備

  • まずプロジェクトを作成します。空プロジェクトから設定するよりはARテンプレートを使うと、ある程度初期設定をしてくれるので便利です

  • プロジェクトが開けたら、AndroidまたはiOSにChange Platformします

  • 次にPackage ManagerからGoogle ARCore Extensions for AR Foundationをインストールします

  • Package Managerを開いたら左上の+から Add package from git URL...を選択し下記のURLを入力します。AddするとARCore Extensionsがインストールされます

https://github.com/google-ar/arcore-unity-extensions.git
  • ARCore Extensionsを選択するとGeospatialのSampleがインポートできるようになっているので、こちらもインポートしておきます

  • 次にProjectの設定を行います。まずXR Plug-in Managementを開き、AndroidであればARCore iOSであればARKitを有効にします

  • さらにARCore Extensionsの設定を開き Authentication StrategyAPI Keyに変更し、先ほど入手したAPIキーを貼り付けます

  • Optional FeaturesのGeoSpatialにチェックを入れます

  • また、iOSの場合は iOS Support Enabledにチェックを入れてください

  • iOSの場合はGPSを利用する際に表示するメッセージを設定する必要があります。PlayerSettings->Other Settings->Location Usage Descriptionに任意のメッセージを入れます。これが入っていないとビルドエラーになってしまいます。

  • Assets/Samples/ARCore Extensions/1.31.0/Geospatial Sample/Configurations/GeospatialConfigを開きGeospatial ModeがEnabledになっていることを確認します

これで準備完了です、Geospatialシーンをビルドします
(Development Buildにチェックを入れると、アプリ上でGeospatialのステータスが見られるようになります)

実際に使ってみる

アプリを開くと最初はこの画面が表示されるので、Get Startedをタップします

アプリが起動して、しばらくカメラを向けているとLocalizeが成功して Localization completedが表示されます
そうするとSET ANCHORのボタンが現れ、オブジェクトを設置することができるようになります
アプリがすぐ閉じてしまう場合は、下記のトラブルシューティングを参考にしてみてください

精度について

画面上に表示されている数値の意味は下記のとおりです

意味
Latitude・LAT 緯度
Longitude・LNG 経度
Altitude・ALT 高度
Horizontal Accuracy 緯度と経度の推定水平精度[m]
Vertical Accuracy 推定高度精度[m]
Heading 方位
Heading Accuracy 推定方位精度

Heading Accuracyについては下記のドキュメントが詳しいです。Heading Accuracy=10だった場合、Headingの±10度になる可能性が68%だそうです。Heading Accuracyの値が低いほど精度が高いことを示します。

https://developers.google.com/ar/develop/unity-arf/geospatial/developer-guide-android?hl=ja#adjust_for_pose_accuracy

任意の場所にオブジェクトを配置する

あらかじめオブジェクトが起きたい位置が決まっている場合、緯度・経度・高度・回転を与えることで、その場所にオブジェクトを配置することができます

using Google.XR.ARCoreExtensions;

if (earthTrackingState == TrackingState.Tracking)
{
  var anchor =
      AnchorManager.AddAnchor(
          latitude,
          longitude,
          altitude,
          quaternion);
  var anchoredAsset = Instantiate(GeospatialAssetPrefab, anchor.transform);
}

https://developers.google.com/ar/develop/unity-arf/geospatial/developer-guide-android?hl=ja#place_a_geospatial_anchor

トラブルシューティング

error CS0234: The type or namespace name 'iOS' does not exist in the namespace 'UnityEditor' (are you missing an assembly reference?)

これはiOSのモジュールがインストールされてない場合に表示されます。UnityHubからiOSのモジュールをインストールするか、該当の個所を#if UNITY_IOSでくくってコンパイルエラーを消します

ビルドしたアプリがすぐ閉じてしまう

今回使用したサンプルは、エラーが起きるとすぐにアプリを閉じる仕様になっています。しかし、しばらく待つことで初期化が成功することもあるので、ReturnWithReason関数の下2行をコメントアウトしてアプリが閉じないようにします

GeospatialController.cs
private void ReturnWithReason(string reason)
{
    if (string.IsNullOrEmpty(reason))
    {
	return;
    }

    SetAnchorButton.gameObject.SetActive(false);
    ClearAllButton.gameObject.SetActive(false);
    InfoPanel.SetActive(false);

    Debug.LogError(reason);
    SnackBarText.text = reason;
    //_isReturning = true;
    //Invoke(nameof(QuitApplication), _errorDisplaySeconds);
}

EarthStateがErrorInternalになる

  • 通信エラーでアプリがGCPにアクセスできないと、このエラーになるようです
  • 私の場合、Wifiから4Gに切り替えたところ、このエラーは発生しなくなりました

SessionStateがNoneになる

XR Plug-in ManagementARCoreまたはARKitが有効になっていないと、Sessionの初期化が走らずSessionStateがNoneになるようです

Discussion

分かりやすい解説記事をありがとうございます!

1点気になる所がありまして、こちらの環境では記事の通りにやると下記のようにErrorInternalという風に出てアプリがすぐ落ちてしまいましたが、Geospatial ConfigのGeospatial modeをdisabledにすると直ってサンプルがそれらしく動きました。中身や違い等はまだ把握できてませんが一旦共有です。

私も GeospatialConfig のところは Disable (デフォルト)だったのを Enable にしたら、アプリ最初の「Get started」 が出ませんで開始できませんでしたが、
Disable のままにしたらアプリが先に進められ、位置取得が出来ました。

私はAndroid でしたので、iOS 版と挙動が異なるのかもしれませんので参考までに。

素晴らしい記事をありがとうございます。

神記事ありがとうございます!

ReturnWithReason関数の下2行をコメントアウトしてアプリが閉じないようにします

私の端末だとコメントアウトしないと一切先へ進めなかったため非常に助かりました!!

私もUnityでAndroidアプリを作成して試したところ、疑問に思った事がありますので共有させて頂きます。
この新API。GoogleBlogに書かれているように「カメラ画像をストリートビューを元にしたモデルに照会してデバイスの位置と向き決定」を"してなくない"ですか?
ストリートビューと変わりがない特徴的な建物が多い場所をあちこち歩きながらテストしたのですが、
(1)アンカーセットした特徴的な建物やその周辺をカメラに映さなくても、その場所に近づけばアンカーのCGがAR表示される
(2)上記(1)で大まかな位置をつかみ新APIできっちり固定AR表示させるのかと思い、アンカーセットした時と同じアングルで特徴的な建物をカメラに映していても、YouTubeデモ動画のようにアンカーしたCGが安定固定AR表示されず、前後左右上下に動いたり消えたりする
と、アプリの挙動が「どうみてもGPSとジャイロ使っているだけ」なんです。
GCPのAPI使用状況をチェックしますと利用はされているのですが、、、。
AndroidStudio向けのサンプルで試した方がよいのでしょうかね??

おそらく内部の動作はGPSでおおよその位置を決定してから、VPSで微調整しているのだと思います
カメラを隠したりするとHorizontal Accuracyの値が悪くなり、周りを見渡すと値が良くなるのでその辺でVPSが機能しているかどうかを確認できると思います

ご返信ありがとうございます!
勉強になります。

さきほどAndroidStudioをインストールし、下記サンプルコードを試そうとしたのですが、2ページ目の「プロジェクトを確認する」の段階で画面下半分にGoogleMapが表示されず詰んでおります。。。

https://developers.google.com/ar/develop/java/geospatial/codelab#0

Android Nativeの方は試していないので、ちょっとわかりません
申し訳ないです

情報とても役に立ちました!
ARcoreテンプレート使わずに試したらEarthStateがErrorInternalになる現象起きてしまい記事を参考にテンプレ使ったら解決できました。
差分を潰して行ったところ原因はデフォルトで設定されてたproguard.txtでライブラリ読めないらしきエラーが出ていた事でした。
テンプレ使わない人はここら辺見直すと良さそうです

ログインするとコメントできます