microsoft / MixedReality-WorldLockingTools-Unity

Unity tools to provide a stable coordinate system anchored to the physical world.
https://microsoft.github.io/MixedReality-WorldLockingTools-Unity/README.html
MIT License
188 stars 45 forks source link

Alignment with a single image target #203

Closed rolandsmeenk closed 3 years ago

rolandsmeenk commented 3 years ago

In many of our HoloLens projects we use a Vuforia ImageTarget or OpenCV Charuco detection to align holograms with the physical world and/or synchronize holograms between multiple users in a networked session. Typically that location will be given a WorldAnchor and the holograms are often fairly small scale (about 2x2 meter). We now want to update these projects to use WLT as it is the preferred way to go forward. Despite the elaborate documentation and samples I still don't entirely understand how to make this work with WLT. When an image target is recognized a transform is constructed that acts as the parent for all holograms. Am I correct in assuming that this transform is in Spongy space since it calculated with the then estimated HoloLens position? And how do I bring it into World locked space?

fast-slow-still commented 3 years ago

Hi Roland,

You have several approaches available to you. The most straightforward, and requiring the least changes from what you have been doing, is to:

  1. Continue constructing the parent transform for all holograms
  2. Correct the Pose returned by ImageTarget/Charuco into Frozen Space (Unity global space).
  3. Omit the WorldAnchor from the parent transform.

Steps 1. and 3. are straightforward.

Doing step 2. properly requires knowing what space the image tracking APIs are returning their results in. It is almost certainly either Frozen Space or Spongy Space. If the API ignores the transform of the parent of the camera in returning Poses, then it is Spongy Space. If it folds in the transform of the parent of the camera, it is Frozen Space. I would suggest determining it experimentally. Let me know if I can be helpful in that.

Having determined the space your detection API returns its result in, life gets easy again.

If the result is in Frozen Space, then it is already in Unity global space, so just set that as the Pose of the hologram parent transform.

If the result is in Spongy Space, first convert it to Frozen Space, and then set it to the hologram parent. The conversion is simply:

Pose frozenPose = WorldLockingManager.GetInstance().FrozenFromSpongy.Multiply(spongyPose);

Note that FrozenFromSpongy is not constant, it changes over time as WLT adjusts the camera pose to keep the global coordinate space (Frozen Space) locked relative to the physical environment. So query it when you want to use it, and don't cache its value.

Other approaches

I mentioned there are other approaches to doing this in WLT. I think the above will work fine for what you are doing, but for completeness I'll briefly describe the other approaches and point to samples.

Pin the whole space instead of the root of the object tree.

If you look at the QR Code Sample, it does something very similar. It scans a number of QR codes placed in the physical environment, and uses them to align the entire coordinate space to your room. Then your holograms can be loaded with the coordinates in which they are modeled, and will drop into your physical scene as intended.

This also allows you to pin your scene at multiple points, rather than based on a single detected image. See below.

Pin your subtree at multiple points

Because the placement of your holograms is controlled at a single point, where the image was scanned and the parent node is, then the farther you get from that point, the larger the errors will be.

For a small model like you describe, this shouldn't be an issue. But if your model gets larger, then even if very accurately placed at the parent node, it will have substantial registration error on the periphery.

By scanning multiple images around the outer bounds of your model, you can eliminate those errors as well. This is true for using Space Pins to lock the entire world as in the above example, or for locking only a subtree, as seen in the Align Sub Scene example. A sample of the combination of using QR codes to align a sub scene is also included.

fast-slow-still commented 3 years ago

Apologies about taking so long to get back to you, I was away last week. Please let me know if I can clarify any of the points above, or be helpful in any way. Feel free to email me directly if that seems more efficient. Also, if this resolves your issue I'd be interested in hearing that as well. Thanks!

rolandsmeenk commented 3 years ago

Looks like I ran into a pitfall where I kept the default values, but on Unity 2020 WSA is no longer available. When I ran that on the HoloLens the program got stuck without telling me why. Would be handy if the default would depend on the unity version that is used. After I switched the Anchor System to XRSDK the locking seems to work.

I don't have the definitive answer for the coordinate frame yet, but I think the answer is hidden in the TryGetCameraToWorldMatrix (https://github.com/VulcanTechnologies/HoloLensCameraStream/blob/master/HoloLensCameraStream/Plugin%20Project/VideoCaptureSample.cs) because that is what is used to construct the parent transform for a Charuco detected with OpenCV.

With the single marker there is indeed a bit of drift when the head is moving left or right from the original position. I will look at pinning at multiple locations to counter this.

fast-slow-still commented 3 years ago

When upgrading a project, or starting a new project, or substantially altering a project's configuration, it's a good practice to run the Configure Scene tool, then check that a valid anchor management subsystem was chosen. The Configure Scene tool can be found in the Unity menu here: ConfigureScene

If it chooses the "Null" subsystem, it means there is a problem with your scene's configuration, and you are unlikely to get an AR experience at all. E.g.: image

Let me know if I can be helpful with your project moving forward, especially if you start working with SpacePins.

Closing this issue for now. Feel free to reopen or open a new issue if you hit new problems.