ARCore Geospatial APIで任意の地点に3Dモデルを表示する

はじめまして。

タクシーアプリ『GO』のAndroidアプリを開発している石橋です。

GO株式会社には半年に2週間、業務を離れて自分の興味のある内容に取り組むことができる「Engineer Challenge Week (ECW)」という制度があります。

ECWで、ユーザー課題を解決するために、ARCore Geospatial APIを『GO』へどのように導入可能なのか検討してみました。

ARCore Geospatial APIとは

ARCore Geospatial APIとは、2022年5月にGoogleが提供するARフレームワーク「ARCore」に追加されたVPS(Visual Positioning System)です。

Googleストリートビューが利用できる場所ならどこでも利用が可能です。

スマホのセンサーやGPSの情報、カメラ映像などがGoogleストリートビューで使用されている数百億の画像から構築されたモデルと照合されるため、開発者が事前に空間をスキャンする必要が無く、スマホの現在の位置や向きを正確に特定したり、指定した緯度経度の地点に現実世界に重ね合わせて3Dモデルを表示することが可能となっています。

ARCore Geospatial APIを使うための準備

プロジェクトを新規作成し、ARCoreを有効化する

Geospatial APIを利用するためには、アプリで認可を行う必要があります。

キーレス認証もありますが、今回はAPIキーでの認証を行う方法で説明させていただきます。

まずは、Google Cloudのコンソールにログインして新しいプロジェクトを作成します。

次に、メニューの「有効なAPIとサービス」を選択し、「+ APIとサービスの有効化」からARCore APIを選択し有効化します。

APIキーを作成する

ARCore APIを有効化したら、Geospatial APIを使えるようにするためのAPIキーを作成します。

APIキーの作成は、メニューの「認証情報」を選択し、「+認証情報を作成」から行います。

APIキーの作成が完了したら、APIキーの一覧に新しく作成したAPIキーが作成されていることが確認できると思います。

必要に応じてAPIキーに対しての制限を行なってください。

制限としては、特定のウェブサイト、IP アドレス、Android アプリ、または iOS アプリからのアクセスに限定する制限や使用できるAPIの種類での制限などを設定することができます。

AndroidアプリでGeospatial APIを使えるようにする

以下のように、先ほど作成したAPIキーを「AndroidManifest.xml」に設定します。

詳しい手順については、ARCoreのドキュメントのAndroid アプリ(Kotlin/Java)で Geospatial API を有効にする を参照してください。

Anchorを生成して任意の地点に3Dモデルを表示する

では実際にGeospatial APIを使って、任意の地点に3Dモデルを表示してみましょう。

ここからはGoogleが公開している、Geospatial APIのCodelabのサンプルアプリを例に説明していきたいと思います。サンプルアプリのソースコードこちらで確認することができます。

Geospatial APIを手っ取り早く試してみたいのであれば、このサンプルアプリをベースに実装してみるのがおすすめです。

Anchorを生成して、任意の地点に3Dモデルを表示する処理は HelloGeoRenderer.kt に書いていきます。

HelloGeoRenderer.kt

class HelloGeoRenderer(
    val activity: HelloGeoActivity,
) : SampleRender.Renderer, DefaultLifecycleObserver {
    
    ・・・

    var earthAnchor: Anchor? = null
    val latLng = LatLng(24.2867, 153.9807) // 例.東京駅の緯度経度
    
    override fun onDrawFrame(render: SampleRender) {
        val session = session ?: return
        val earth = session.earth
    
        // 指定した緯度経度にAnchorを生成する 
        earthAnchor = earth?.createAnchor(
      latLng.latitude,   // 緯度
      latLng.longitude,  // 経度
      earth.cameraGeospatialPose.altitude,
      0f,
      0f,
      0f,
      1f
        )
                
        // Anchorの位置に3Dモデルを表示する
        earthAnchor?.let {
      render.renderMarkerAtAnchor(it)
    }
    }

    // Anchorの位置に3Dモデルを描画するためのメソッド
    private fun SampleRender.renderMarkerAtAnchor(anchor: Anchor) {
    anchor.pose.toMatrix(modelMatrix, 0)

    Matrix.multiplyMM(modelViewMatrix, 0, viewMatrix, 0, modelMatrix, 0)
    Matrix.multiplyMM(modelViewProjectionMatrix, 0, projectionMatrix, 0, modelViewMatrix, 0)

    virtualObjectShader.setMat4("u_ModelViewProjection", modelViewProjectionMatrix)
    draw(virtualObjectMesh, virtualObjectShader, virtualSceneFramebuffer)
  }
}

作成したデモアプリ

タクシーアプリ『GO』にはタクシーを呼んでタクシーの配車が完了した後、指定した乗車地点と呼んだタクシーの位置が表示される画面があります。

この画面では、自分が現在いる位置と乗車地点が地図上で表示されますが、なかなか乗車地点を見つけられない場合もあるかと思います。

なので今回は、先ほど紹介したGeospatial APIで任意の地点に3Dモデルを表示するコードを実際に『GO』のアプリに組み込んで乗車地点をARCoreで表示してみる検証を行いました。

デモアプリでは、『GO』のアプリで実際に配車を行って指定した乗車地点にARCoreでPointerを表示するのに加え、現在地から乗車地点までの経路上に3Dモデルを表示し、乗車地点までの距離を表示するようにしています。

現在地から乗車地点までの経路はGoogle Maps PlatformのDirections APIを利用して取得しています。

ARCoreで乗車地点や経路を表示することで、既存の2Dのマップに表示されている位置情報よりも直感的に乗車地点の場所が把握できるようになることが期待できそうです。

今後の課題

今回は現在地から乗車地点までの経路をDirections APIで取得し、その経路上に3Dモデルを表示しました。

追加でAnchorの間を線で結んだり乗車地までナビゲーションできるような機能を入れていけたら、よりわかりやすくユーザーを乗車地点まで案内できるアプリになりそうなので、次のステップとして挑戦していきたいです。