Hello everyone.

We have decided to phase out the Mixed Reality Forums over the next few months in favor of other ways to connect with us.

The first way we want to connect with you is our mixed reality developer program, which you can sign up for at https://aka.ms/IWantMR.

The plan between now and the beginning of May is to clean up old, unanswered questions that are no longer relevant. The forums will remain open and usable.

On May 1st we will be locking the forums to new posts and replies. They will remain available for another three months for the purposes of searching them, and then they will be closed altogether on August 1st.

So, where does that leave our awesome community to ask questions? Well, there are a few places we want to engage with you. For technical questions, please use Stack Overflow, and tag your questions using either hololens or windows-mixed-reality. If you want to join in discussions, please do so in the HoloDevelopers Slack, which you can join by going to https://aka.ms/holodevelopers. And always feel free to hit us up on Twitter @MxdRealityDev.

World anchor interferes with changing position of object

lillemorblillemorb
edited March 2017 in Questions And Answers

The TL;DR:

I am trying to alter the position of an object that has a world anchor/spatial anchor. I have two functionalities that each removes the anchor, alters the position and then attaches a new anchor. Only one of the functions work, though to me they seem to do almost the same thing.

The long version:

I'm doing a simplistic 3D app where the aim is to be able to position a number of spheres by dragging them with a gesture, with the spheres remembering their new position the next time I open the app.

I started with some prefabs and scripts from HoloToolkit-Unity. To introduce being able to reposition the sphere by dragging it, I attached Handdraggable.cs to the sphere. For interaction with the spatial map and position persistence through world anchors, I borrowed that functionality from TapToPlace.cs .

My element hierarchy, where SphereIcon is the sphere:

The problem

My problem is with a short reset function I wrote, which is supposed to reset the position of the sphere to where the user is looking. It worked as intended when I accidentally had attached a rigidbody to the sphere, which breaks the world anchor functionality. When I realized that and removed the rigidbody, everything worked except reset. When resetting, the sphere can be seen as a flicker in the intended position, then it returns to the old position.

The script uses the WorldAnchorManager from HoloToolkit-Unity.

I know that to change the position of an object that has a world anchor, you need to remove the anchor, alter the position and then attach a new world anchor, as described by Microsoft here.

The code for dragging the object

I have borrowed the code for the anchor management from the OnInputClicked method in TapToPlace.cs (line 126).

I have a WorldAnchorManager that is initiated as follows:

protected WorldAnchorManager anchorManager;
protected virtual void Start()
{
     anchorManager = WorldAnchorManager.Instance;
     if (anchorManager == null)
     {
           // Debug printout
     }
}

The dragging is started by doing a hold gesture, the anchor on the object is removed so that the position of the object's transform can be altered:

    public void OnInputDown(InputEventData eventData)
            {
                if (isDragging)
                {
                    // We're already handling drag input, so we can't start a new drag operation.
                    return;
                }
                if (!eventData.InputSource.SupportsInputInfo(eventData.SourceId, SupportedInputInfo.Position))
                {
                    // The input source must provide positional data for this script to be usable
                    return;
                }

                currentInputSource = eventData.InputSource;
                currentInputSourceId = eventData.SourceId;

                anchorManager.RemoveAnchor(gameObject);

                StartDragging();
            }

StartDragging() does some setup, and UpdateDragging() is called from Update() to change the position of the objects transform as the user drags their hand. There are a lot of calculations in UpdateDragging() ending with:

    HostTransform.position = draggingPosition + mainCamera.transform.TransformDirection(objRefGrabPoint);
    HostTransform.rotation = draggingRotation;

The code for ending the dragging by releasing the hold gesture, and attaching a new anchor to the sphere:

    public void OnInputUp(InputEventData eventData)
          {
                if (currentInputSource != null &&
                        eventData.SourceId == currentInputSourceId)
                {
                        StopDragging();                           
                 }

                // Add world anchor when object placement is done.       
                anchorManager.AttachAnchor(gameObject, SavedAnchorFriendlyName);           
           }

The code for reset

The code for resetting the position of the SphereIcon:

private void OnReset()
        {
                // Remove anchor
                anchorManager.RemoveAnchor(gameObject);

               // Alter the position of the object (HostTransform), basically what is done in
              // UpdateDragging() when dragging the object
               HostTransform.position = Camera.main.transform.position
                        + Camera.main.transform.forward * originalDistance;

               // Attaching a new anchor
                anchorManager.AttachAnchor(gameObject, SavedAnchorFriendlyName);
        }

By printing some trace printouts of the object position to Debug.Log I have figured out that this happens when I reset the position (if not stated otherwise, all of the following is done in the customized Handdraggable-script attached to the sphere):

  1. The anchor is removed
  2. The position of the sphere is altered
  3. The WorldAnchorManager method AttachAnchor (line 86 in WorldAnchorManager.cs) is called with a gameObject that has the correct position (as seen through printouts from within AttachAnchor)
  4. AttachAnchor enqueues the create operation (line 100)
  5. An Update() is executed from the main script (ie the altered Handdraggable) with the correct, new position
  6. Another Update() is executed with the incorrect, old position for some reason
  7. The WorldAnchorManager method DoAnchorOperation (line 177) creates the anchor, but with the gameObject now having the incorrect, old position
  8. The position of the object does not change after this

There are always two Update() events with one correct and one incorrect position, as stated above. The incorrect behaviour is there regardless of debug printouts. The hand dragging functionality seems to work exactly as inteded, with the object remaining in the exact position as when the motion ends - not reverting to the position before the last that would be more in line with the error in the reset function. I haven't found any code that makes alterations of the position of the object's position or of the parents' positions which could interfere.

The reset and the hand dragging methods are both in the same script, attached to the sphere. The reset event is done by a message broadcast, either from the SpeechManager when "Reset" is spoken or from a script attached to a reset button when the button is clicked. The OnInputDown and OnInputUp triggered by the hand dragging motion is handled by one of the prefabs/existing scripts. I don't know if that makes any difference.

I have no idea why the dragging functionality behaves correctly but the reset function does not. Any idea of what the problem could be or what I could look at?

Edit: edited to better explaining the problem.

Best Answer

  • lillemorblillemorb
    Accepted Answer

    I circumvented this problem and didn't think about it for several weeks. Then I realized that the operations to remove and attach an anchor are asynchronous. I think the problem is that I am trying to both remove and attach an anchor in one frame. When I remove the anchor, change the position of the sphere and then attach a new anchor, the old anchor still exists. This means that I will attach the old anchor to the sphere instead of a new one, and the sphere will get the incorrect position of the old anchor (if I have understood correctly from the doc about the AttachAnchor method in WorldAnchorStore).

Answers

  • lillemorblillemorb
    Accepted Answer

    I circumvented this problem and didn't think about it for several weeks. Then I realized that the operations to remove and attach an anchor are asynchronous. I think the problem is that I am trying to both remove and attach an anchor in one frame. When I remove the anchor, change the position of the sphere and then attach a new anchor, the old anchor still exists. This means that I will attach the old anchor to the sphere instead of a new one, and the sphere will get the incorrect position of the old anchor (if I have understood correctly from the doc about the AttachAnchor method in WorldAnchorStore).

Sign In or Register to comment.