MRTKとWLTの組み合わせで起こった空間メッシュ取得の不具合|DAFTCRAFT ENGINEER BLOG

弊社ではMRTK(MixedReality Toolkit)とWLT(World Locking Tools)を使ったHoloLens2用のアプリケーションを開発しています。
このMRTKとWLTの組み合わせで、空間メッシュの取得に問題がおきました。QRコード認識とWLTのSpacePinを使って位置合わせをすると、MRTKの空間メッシュの取得範囲がズレるという問題です。

今回の記事では、この問題への対応として行ったことと、そこから分かった問題の原因について記録していきます。なお、この問題は現時点(2022/03/23)で最新のMRTK 2.7.3で起こっていますが、MRTK 2.7.4で修正される予定です。

https://github.com/microsoft/MixedRealityToolkit-Unity/milestone/27

 

環境

  • HoloLens2
  • Unity 2020.3.30f1
  • MRTK 2.7.3
     OpenXR Plugin 1.3.1
  • World Locking Tools  1.5.7

対応


この問題はSpatialAwarenessのOpenXRSpatialAwarenessMeshObserverの基準位置の扱いで起こっています。そこで基準位置の問題を修正したSpatialMeshObserverを作り、それを使うようにすることで対応できます。

				
					namespace Daftcraft.Utilities.Observers
{
  [MixedRealityDataProvider(
        typeof(IMixedRealitySpatialAwarenessSystem),
        SupportedPlatforms.WindowsStandalone | SupportedPlatforms.WindowsUniversal,
        "Temporary OpenXR Spatial Mesh Observer",
        "Profiles/DefaultMixedRealitySpatialAwarenessMeshObserverProfile.asset",
        "MixedRealityToolkit.SDK",
        true,
        SupportedUnityXRPipelines.XRSDK)]
  public class TemporaryOpenXRSpatialAwarenessMeshObserver
      : OpenXRSpatialAwarenessMeshObserver
  {
      public TemporaryOpenXRSpatialAwarenessMeshObserver(
          IMixedRealitySpatialAwarenessSystem spatialAwarenessSystem,
          string name = null,
          uint priority = DefaultPriority,
          BaseMixedRealityProfile profile = null)

           : base(spatialAwarenessSystem, name, priority, profile)
      {
      }

      protected override void ConfigureObserverVolume()
      {
          // (1) Playspaceのローカル座標に変換
          ObserverOrigin = MixedRealityPlayspace.InverseTransformPoint(ObserverOrigin);

          base.ConfigureObserverVolume();
      }
  }
}
				
			

この対応の要点は(1)の座標変換です。ではなぜこの座標変換が必要になるか考えていきます。

 

座標変換が必要な理由


まずMRTKの空間メッシュは、認識した空間のメッシュを全て取得しているのではなく、一定の範囲を取得するようになっています。HoloLens2は独立して空間を認識し、MRTKのオブザーバが必要な分の空間情報をAPIから取得し処理する流れです。MRTKのデフォルトでは、プレイヤーの位置を中心とした3m x 3m x 3mの軸固定立方体(AABB: Axis-Align Bounding Box)が範囲です。つまり空間メッシュの取得範囲はプレイヤーを中心とした1辺6mの立方体です。本来は3次元ですが、簡単のためY軸の上方向から下方向に見たXZ平面(2次元)を考えます。その時の取得範囲が以下の図です。プレイヤーを中心として、X方向とZ方向にプラスマイナス3mずつの1辺6mの正方形になります。AABBなのでプレイヤーの向いている方向は関係ありません。

次にプレイヤーの位置について考えます。MRTKではプレイヤー(MainCamera)をMixedRealityPlayspace(以下Playspace)という名前のGameObjectの子にしています。WLTではPlayspaceの親オブジェクトを作り、それを動かす事で位置合わせをしています。

  • プレイヤーはPlayspaceの中を動き回る
  • Playspaceの位置はAdjustmentを動かして調整

のイメージです。

トラッキング中の人の動きはプレイヤー(MainCamera)のlocalPositionとlocalRotationに反映されます。トラッキング開始点が原点なので、反映されるのはそこからの相対的な位置と向きです。これは親オブジェクトであるPlayspace基準のローカル座標です。空間メッシュはトラッキングしている人の周りに欲しいので、このPlayspace基準のプレイヤーの座標を取得すれば良いことになります。そのためMRTKではMixedRealityPlayspaceクラスからPlayspaceに簡単にアクセスできるようになっています。

 

原因

 

WLTの位置合わせで空間メッシュの取得範囲がズレる問題は、このPlayspace基準のプレイヤー位置を使っていなかったことに起因します。プレイヤーのワールド座標が空間メッシュ取得の基準点となっていました。

位置合わせをしない場合は、Playspaceの原点はワールドの原点と同じになるため、プレイヤーの位置はワールド座標でもPlayspaceのローカル座標でも同じです。しかし、位置合わせをするとPlayspace自体の位置が変わるため、プレイヤーのローカル座標とワールド座標は位置合わせのオフセットだけ差が生まれます。実際には位置だけではなく向きも補正されるのでワールド座標とローカル座標の違いはさらに大きくなります。つまりプレイヤーの位置はワールド座標とローカル座標で表している情報が違います。プレイヤーのローカル座標はトラッキング情報で、ワールド座標はUnity内で決めるコンテンツの位置の情報と言えます。トラッキングの位置情報を使うはずが、コンテンツの場所に調整後の位置を使っていたことが取得範囲のズレの原因です。

このワールド座標をPlayspace基準の座標に変換する処理が、対応の(1)の部分です。ワールド座標をPlayspaceのローカル座標に変換する事で、本来のプレイヤーの位置(トラッキング情報)に合わせた処理に修正できます。

 

あとがき


今回の問題の原因は単純で、MainCameraの位置をローカル座標ではなくワールド座標で扱っていたことでした。しかし、この単純な座標の取り方の違いは、一方はトラッキング情報で、もう一方はコンテンツ内の位置であるという意味の違いを含んでいます。つまりプレイヤーの座標の取り方で関心の対象が現実空間なのかUnity空間なのか分かります。この違いを意識すると、空間メッシュやトラッキングの情報の流れも見えてくると思います。

Picture of 岩城 謙太

岩城 謙太

XR Engineer