先日の記事で紹介したARKitで絵を描くデモと同じく有名なのがARメジャーアプリ。

※ARKitで絵を描いてみた前回記事はこちら
https://techpartner.jp/blog/drawing

今回は、メジャーアプリを作る上での基礎となる、ARkitを用いた距離計測を実装してみます。

実装する内容

ARKitを用いた距離計測を実現する流れは下記となります。

  • 始点と終点を照準するための画像を画面の中心に設置
  • 始点と終点の座標をhitTest(_:types:)を利用して取得
  • 始点、終点の2点間の距離を計算

また、始点と終点に球体のノードを設置し、線のノードでつなぐ事で
メジャー風のビジュアルを実現します。

以下に実装内容の詳細を記載します。
※ARKitの基本的な実装は、今回の説明からは省略しています。

画面の中心に照準画像を設置

画面の中心にスコープ画像を設置し、始点、終点を指定できる様にします。

※利用させていただいた画像
https://www.flaticon.com/free-icon/target_149231#term=target&page=1&position=2

hitTestで始点、終点座標を取得

ARSCNViewのhitTestを利用して、ヒットした箇所のワールド座標を取得します。

hitTest(_:types:)について

  • パラメータ
    • 第1引数はCGPoint(2D座標軸)
    • 第2引数はARHitTestResult.ResultType(検出タイプ)
  • 戻り値:
    • ARHitTestResult型の配列。※カメラから近い順にソートされる
      • .worldTransform: simd_float4x4型 (4×4の変換行列)

※参考
https://developer.apple.com/documentation/arkit/arscnview/2875544-hittest

ARHitTestResult.ResultType

ARHitTestResult.ResultTypeの種類は下記

  • featurePoint (特徴点)
  • estimatedHorizontalPlane (推定の平面)
  • estimatedVerticalPlane (推定の垂直の平面)
  • existingPlane (検出した平面 + 平面サイズを考慮しない)
  • existingPlaneUsingExtent (検出した平面 + 平面サイズを考慮する)
  • existingPlaneUsingGeometry (検出したジオメトリ + 平面サイズとカタチを考慮する)

今回は、平面に限らず距離を計測したいので、featurePointを指定します。

※参考
https://developer.apple.com/documentation/arkit/arhittestresult/resulttype

中心点を取得するメソッド

測定ボタンのタップで計測開始

測定ボタンのタップが終了したら計測終了

始点、終点の2点間の距離を計算

3次元の始点、終点の2点間の距離を計算する公式は下記です。

始点と終点の座標から距離を計算します。

renderer(_:updateAtTime:)で始点、終点をつなぐ線ノードを更新

renderer(_:updateAtTime:)は、フレーム更新毎する度に呼ばれるので、測定中のステータスの時は、線ノードをアップデートし続けます。

線ノードの作成

測定中のステータスの時は、線ノードをアップデートし続ける

実行

MacBook Pro 15インチの横幅は34.93 cmなので、誤差1cm以内で計測できました。

ただ、特徴点でのhitTestの場合、想定と違う位置の座標を取得してしまう事もあるので
今回のラップトップの様に、平面検知が容易な対象の場合は、hitTestのタイプを特徴量でなく、平面アンカーとした方が精度が上がりそうです。

参考にさせていただいた資料