Azure / azure-spatial-anchors-samples

Azure Spatial Anchors sample code
Other
293 stars 139 forks source link

Calling CloudSpatialAnchor.GetPose() complains "Didn't find the anchor" #157

Closed motionsmith closed 4 years ago

motionsmith commented 4 years ago

Hello,

When I call CloudSpatialAnchor.GetPose(), the AnchorHelper says "Didn't find the anchor" and then returns Pose.Identity. Because of this, the anchor appears at the world origin instead of the correct spot. See the code below.

// My own watcher handler
private void Find_AnchorLocated(object sender, AnchorLocatedEventArgs args)
        {
            switch (args.Status)
            {
                case LocateAnchorStatus.Located:
                case LocateAnchorStatus.AlreadyTracked:
                    MainThreadDispatcher.Instance().Enqueue(() =>
                    {
                        Pose pose = args.Anchor.GetPose(); // Throws a log "Didn't find the anchor" and returns Pose.Identity
                        var anchorAvatar = GameObject.Instantiate(AnchorAvatarPrefab, pose.position, pose.rotation, AnchorRoot);
                        var cloudNativeAnchor = anchorAvatar.gameObject.AddComponent<CloudNativeAnchor>();
                        cloudNativeAnchor.CloudToNative(args.Anchor);
                    });
                    break;
            }
        }

Inside the AnchorHelpers.GetPose(IntPtr) extension is where the failure occurs. For some reason the ARReferencePoint is sometimes returning null, given my anchorPointer.

// Inside AnchorHelpers.GetPose(IntPtr)
ARReferencePoint referencePoint = SpatialAnchorManager.ReferencePointFromPointer(anchorPointer);

            if (referencePoint == null)
            {
                Debug.Log("Didn't find the anchor");
                return Pose.identity;
            }

I'm on ASA 2.2.1 and Unity 2019.3 for iOS. Note that I am necessarily calling GetPose() inside the Unity thread. It doesn't seem to matter whether the anchor status is "Located" or "AlreadyTracked" for GetPose to fail. Sometimes GetPose() DOES return a valid pose under identical conditions, so that makes me think this is a race condition.

darax commented 4 years ago

It sometimes takes a frame or two before Unity finds the anchor ASA creates and puts it in their internal list. The samples don't actually ask for the pose until the frame (actually 2 frames) after the anchor located event triggers. Edit: It looks like you might be waiting a frame also. Are you using SpatialAnchorManager? it actually does wait for Unity to have the reference point in its list before raising the event.

motionsmith commented 4 years ago

Thanks for your help @darax. I found the issue, it was a symptom of this bug: https://github.com/Azure/azure-spatial-anchors-samples/issues/112

In my LocateCompleted handler, I removed the AnchorLocated listeners. But since LocateCompleted can be called before AnchorLocated, the first Find operation never handled the AnchorLocated events though anchors were located. That broke subsequent find operations when ASA (or iOS) expected those anchors to have been created earlier.

So, I successfully worked around it by not removing my AnchorLocated and AnchorLocateCompleted handlers after the find operation completes.