ARアンカーのトラッキング
物理的環境内の注目地点を指定、追跡する。
概要
アンカーとは、AR sessionによってトラッキングされる物理環境内のあらゆるものを指します。仮想コンテンツを配置する際は ARAnchor インスタンスを追加し、コンテンツをそれらにアタッチしてください。時間が経つにつれてARセッションの環境理解が更新されたとしても、これを行っておくことでコンテンツの位置が安定しやすくなります。
ARセッションがそのように構成されていれば ARPlaneAnchor および ARImageAnchor オブジェクトが検知されてセッションに自動的に追加されます。仮想コンテンツも同じようにそうしたアンカーにアタッチ可能です。
注釈
ARDKは現在、フェイストラッキングや顔とアンカーを組み合わせた使用には対応していません。
使用例
ARアンカーは非ARの3Dアプリケーションには起こらない問題の解決を行うものであるため、その使用は直感的に感じられないかもしれません。
ARセッション中、フレームは現実世界におけるデバイスの位置を可能な限り正確に推定します。デバイスの位置に対して仮想オブジェクトを配置しようとすると、ズレやカクつきが発生することがありますが、これは推定値に含まれる小さなエラーが、それらをもとに他の変換が導き出されることで増長してしまうために起こります。 ARAnchor
を作成すると、現実世界の1点をトラッキングしたいということがセッションに伝えられ、その点に対する最善の推定が維持されます。セッションは潜在するトラッキングデータにアクセスできるため、点の位置に対するこの推定は複合エラーを回避します。
そのため、現実世界に仮想オブジェクトを配置したい時はアンカーの使用が重要です。たとえば、室内に仮想の家具を設置できるアプリケーションを考えてみましょう。ユーザーにとって重要なのは、配置した仮想のテーブルが現実世界のラグとの位置関係を維持できることです。そのため配置場所が決まったらラグの中央に ARAnchor
を作成し、フレームごとにテーブルの位置を更新してラグとの最初の位置関係を維持しましょう。そうすることでカメラのズレによる影響を受けなくなります。
それからユーザーが壁の隣に本棚を置こうとすると、今度は壁に ARAnchor
が必要になります(すでに表出しているものがある場合は PlaneAnchor
の使用)。これは本棚にとってはラグよりも壁との位置関係のほうが重要だからです。潜在するトラッキングアルゴリズムが継続的に世界理解を更新するため、ここでは副作用として本棚とテーブルの位置関係が動く可能性があります。初めは本棚とテーブルの間の距離が2メートルと判断されていても、別の視界を得ることで位置が修正され、その距離が1.8メートルになるかもしれません。
一方、ユーザーがテーブルの周囲に椅子を配置したいと思った場合は、テーブルが従う既存のARAnchorを基準にして配置されるべきです。椅子にとっては、現実世界の何かよりもテーブルとの位置関係を維持することのほうが重要だからです。
これをまとめると、仮想オブジェクトが携帯電話から遠い場所にあるほど、現実世界に対するズレやカクつきが発生しやすくなります。アンカーを作成して利用することで、アンカーに対する位置関係を計算された仮想オブジェクトが、安定性を維持できる領域を作り出せます。
アンカーの追加
ワールドの静止点の位置および方向のトラッキングを開始するには IARSession.AddAnchor(transform) メソッドを使用してARセッションに追加します。
ARAnchor
に結びついた仮想オブジェクトを動かす必要がある時(自動的に、またはユーザーの入力によって):
1メートル以内程度の小さな動きの場合は、仮想オブジェクトに対する
ARAnchor
からのオフセットを更新するだけで対応できます。より大きな動きの場合はオブジェクトの動きが止まるのを待ち、アタッチするための新しい
ARAnchor
を作成します。使用されていない場合、古いARAnchor
は削除してください。
アンカーのトラッキング
ARSession
はアンカーを更新し、アンカーの対象となるオブジェクトが反映され続けるようにします。
アンカーの最新プロパティは IARAnchor インターフェースからいつでも取得できます。
using Niantic.ARDK.AR.Anchors; public class ARAnchorFollower : MonoBehaviour { public IARAnchor Anchor; void Update() { transform.position = Anchor.Transform.ToPosition(); transform.rotation = Anchor.Transform.ToRotation(); } }
また、アンカーの更新をサブスクライブすることも可能です。アンカーは 識別子 プロパティに基づいて比較可能です。
void SubscribeToSession(IARSession arSession) { arSession.AnchorsUpdated += OnAnchorsUpdated; } void OnAnchorsUpdated(AnchorsArgs args) { foreach (var anchor in args.Anchors) { // Find GameObject from Dictionary containing // existing Anchor to GameObject mappings var go = virtualObjects[anchor.Identifier]; go.transform.position = anchor.Transform.ToPosition(); go.transform.rotation = anchor.Transform.ToRotation(); } }