Hello everyone.

The Mixed Reality Forums here are no longer being used or maintained.

There are a few other places we would like to direct you to for support, both from Microsoft and from the community.

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.

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, or in our Microsoft Tech Communities forums at https://techcommunity.microsoft.com/t5/mixed-reality/ct-p/MicrosoftMixedReality.

And always feel free to hit us up on Twitter @MxdRealityDev.

Scene Sharing: position sync is lost when moving the Hologram and re-sending transforms

I've got a scene where the user can tap on an object to move it around, and want to sync the app between two hololenses so that both user see the object in the same position.

I followed the Holograms 240 Sharing course and managed to get a hold of how sharing works and set up a working scene using the Sharing prefabs from the HoloToolkit.

However, I'm facing a problem: the position syncs fine when the application is launched (the object is in the same position for both hololenses), but as soon as one user moves the object, the position in the other hololens jumps off.

The motion is correct on a relative scale (the object moves by the same amount of distance on both hololenses), but the final position is offsetted. The offset is roughly equal to what the distance between the objects would be in the two hololenses if no sync was in place.

So, it's almost like the first position sync is reversed.

Judging from the debug log of the two application, the apps are using the same room, and the anchor is exported and imported correctly, so that's not the issue. I reset the sharing service between every test as well.

I'm using a similar setup to the one in Holograms 240 to place my holograms, a tad simplified:

In my update function, I check if the user is moving the hologram, and once done I send the transform message:

void Update()
    {
        if (ImportExportAnchorManager.Instance.AnchorEstablished) {
            if (objectMover.isPlacing ()) {
                DestroyImmediate (gameObject.GetComponent<WorldAnchor> ());
                transform.position = (Position calculated by raycasting the spatial mapping mesh)
                WorldAnchor anchor = gameObject.AddComponent<WorldAnchor> ();
                GotTransform = true;
            }

            if (!objectMover.isPlacing () && GotTransform) {
                Debug.Log ("*Sending Transform Message");
                sendStageTransform ();
                GotTransform = false;
            }
        }
    }

    public void sendStageTransform() {
        CustomMessages.Instance.SendStageTransform(transform.localPosition, transform.localRotation);
    }

When a message is received, I updated the position accordingly

    void OnStageTransfrom(NetworkInMessage msg)
    {   
        msg.ReadInt64();

        Debug.Log ("*Received Transform Message");
        DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
        transform.localPosition = CustomMessages.Instance.ReadVector3 (msg);
        transform.localRotation = CustomMessages.Instance.ReadQuaternion (msg);
        WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();
    }

When an user joins the session, I send the relative transform for the model.
I check for AnchorEstablished so that the first hololens which has an estabilished anchor and room sends the transforms to the second hololens which joins the sessions afterwards, and not the other way around.
Worth noting that if I skip this check, the initial position is not synced, but the movement works fine (doesn't jump) - so there's definitely something going around here, I just can't pin-point what.

    private void Instance_SessionJoined(object sender, SharingSessionTracker.SessionJoinedEventArgs e)
    {
        if (ImportExportAnchorManager.Instance.AnchorEstablished)
        {
            sendStageTransform ();
        }
    }

Any clue what might be going on here?

Best Answer

Answers

  • leoncvltleoncvlt
    edited July 2016

    @Patrick said:
    I'm not certain that you want to attach a world anchor to your child object.

    The child object must be a child of the object that has the ImportExportAnchorManager attached for this technique.

    If the object is not a child of the ImportExportAnchorManager (IEAM) object then what you need to do is send the object's position relative to the IEAM object and on receiving you need to place the object relative to the IEAM object.

    Something like: (and I'm still sending Quaternions below, I'd switch to Vector 3s most likely).
    sender:

     public void sendStageTransform() {
    Transform IEAMTransform = ImportExportAnchorManager.Instance.transform;
            CustomMessages.Instance.SendStageTransform(IEAMTransform.InverseTransformPoint(transform.position), Quaternion.Euler(IEAMTransform.InverseTransformDirection(transform.rotation.eulerAngles)));
        }
    

    receiver:

     void OnStageTransfrom(NetworkInMessage msg)
        {   
    Transform IEAMTransform = ImportExportAnchorManager.Instance.transform;
            msg.ReadInt64();
    
            Debug.Log ("*Received Transform Message");
            transform.position = IEAMTransform.TransformPoint(CustomMessages.Instance.ReadVector3 (msg));
            transform.rotation = Quaternion.Euler(IEAMTransform.TransformDirection(CustomMessages.Instance.ReadQuaternion (msg).eulerAngles);
         
        }
    

    You'll notice that I'm not using local positions above. Again, this is the case where the object is NOT a child of the IEAM object. If it is then using the local positions is correct.

    Hi Patrick, thanks for coming back at me.

    My mistake was that the IEAM script and the placement script were on the same gameObject. I made a new empty gameObject just for the IEAM and made the hologram with the placement script its child - the position is still not synced when the application fires up, but as soon as a transform message is sent the position syncs correctly in both applications. Thank you!

    So, are you saying that if I have a scenario were the object to be synced is not a child of the IEAM object, the correct workflow is to use IEAMTransform.TransformPoint and IEAMTransform.TransformDirection to set the position, without the need to destroy / recreate WorldAnchors?

    Thanks for clearing this up, it will be useful for future development!

    Cheers,
    L

  • sort of. On the way out you'll use InverseTransformPoint, and on the way in you'll use TransformPoint.

    It takes time (months for me) for this to sink in, but it eventually makes sense. :)

    ===
    This post provided as-is with no warranties and confers no rights. Using information provided is done at own risk.

    (Daddy, what does 'now formatting drive C:' mean?)

  • Does anyone have a better tutorial or example on how this works? The 240 stuff doesn't work well, when it works at all... There's a lot of excess material, and the guide is mostly "Attach this already written script", instead of showing me how it's done.

    I'd really love a sample project that was simply: "Here's two Hololensi looking at the same primitive in the same space"

  • The HoloToolkit has a sharing test scene that is pretty simple.

    ===
    This post provided as-is with no warranties and confers no rights. Using information provided is done at own risk.

    (Daddy, what does 'now formatting drive C:' mean?)

  • That didn't work in my office. It worked in a conference room nearby, but overall, I've not found it to be reliable. I've also had much more luck with the built in Unity networking stuff than I've had with the Sharing Service.

  • Getting the shared point of reference can be challenging. Have you tried running with debugging enabled? It would be useful to know how large the serialized data was for the shared anchor and if there are any messages written to the debugger that could give a clue as to why this isn't working in your office.

    I haven't tried since last November, and I've always been on beta builds, but I've never been successful at getting UNet to work. I need to try it again. I've had Photon working. There's no reason you couldn't use one or the other instead of the sharing service. Managing the serialized data for the shared anchor would be the largest task.

    ===
    This post provided as-is with no warranties and confers no rights. Using information provided is done at own risk.

    (Daddy, what does 'now formatting drive C:' mean?)

Sign In or Register to comment.