Importing anchor Succeeds with 0 anchors?

I'm using Unity3D (tried both 2017.1.1 and 5.6.4) in conjunction with Mixed Reality Toolkit (previously HoloToolkit) in my project. Basically I'm just trying to share a world anchor between multiple devices. I only do this once to establish a common reference. There is no sharing holograms etc. So in essence:

  1. Save a World Anchor with one "master" device.

  2. Share this World Anchor using Unity3D WorldAnchorTransferBatch. I do this by sending the data (byte array) to an intermediate device, an Android phone that also acts as a controller for the whole experience. The Android device acts as a central server which then distributes the anchor data to all connected Hololenses.

  3. Import the World Anchor after transfer from server

  4. Enjoy a common and shared World Anchor in order to reference everything else in the scene.

Now my issue is that transfer works fine but using the WorldAnchorTransferBatch.ImportAsync method it returns a SerializationCompletionReason.Succeeded but contains 0 Anchors. So something doesn't seem quite right here. I already did a bug report to Unity but they are notoriously slow at handling bugs, that being said I guess Unity is basically just wrapping Microsoft code anyway. Does anyone have a slight idea what can be wrong? As of right now the whole project has stalled. :(

Best Answer

Answers

  • > @stepan_stulov said:
    > Hey, @seb
    >
    > You would simply need to retry multiple times. There is no official metric of batch's reliability but someone earlier on the forums simply checked the batch size and retried when it's too small. Batch import reliability issues have been confirmed by Microsoft employee here:
    >
    > https://forums.hololens.com/discussion/1171/worldanchortransferbatch-failures
    >
    > Hope this helps.

    Thanks Stephan. I will try this out. Yet I have to say; how is this not top priority at the MS Hololens team? Not being able to share like this should be a deal breaker for so many projects.

    I'm just curious as to where the export succeeded message is stemming from?

    Jesus, this forum is really crap on mobile.
  • So far the multiply-attempt solution never let me down. Perhaps they de-prioritized this issue due to the availability of this commonly used workaround. One thing I have recently noticed after Windows update on the HoloLens is that they dramatically improved the speed of import/export of the transfer batches. Which is great.

    I'm not entirely sure what Microsoft HoloLens team priorities are but they haven't particularly shined with hearing feedback or being interactive overall, arguably. A bird told me current focus of the team is the immersive headsets, not HoloLens. Perhaps things will change when approaching HoloLens 2 (3) release.

    Building the future of holographic navigation. We're hiring.

  • Ok that makes sense, sadly. But what is your metric for actually determine if the data actually holds an anchor or not? Do you go by size alone? If so; what size?

    I guess I'm fine with any solution at this point as long as it works.

    If I understand you correctly you keep exporting until you reach a certain threshold?
  • I personally didn't implement any reliability metric for the batches but I can clearly remember somebody did this on the forums. I cannon find it anymore though.

    Building the future of holographic navigation. We're hiring.

  • Damn :) thanks anyway. If anyone else has an idea I'm all ears.
  • But surely the very title of your thread is already a metric on its own! Ignore successful imports that give you zero anchors. Cheers

    Building the future of holographic navigation. We're hiring.

  • sebseb
    edited November 2017
    Yeah I guess I could do something like importing on the same device before sending. Good point
  • Hi all,
    thanks for the posts, it it helpful.

    I am also facing the same issue and I would like to try importing anchors multiple times, but I am having difficulty to figure out how to make multiple tries.. I would like to trigger anchor import by a button again and again until it is successful.

    I assume WorldAnchorTransferBatch.ImportAsync(rawAnchorDownloadData, ImportComplete); is responsible of trying to import the anchor, sorry if I am missing an easy point but I am also afraid to mess up the rest of the code which happened once: I added ImportAsync when the count of the imported anchors is 0(you can see below under the comment "for infinitely looking for anchors:").

    I would appreciate if someone shows me the correct direction to go. It is very crucial for my project that the anchors are imported properly...

    Thanks in advance.
    `
    if (AnchorDebugText != null)
    {
    AnchorDebugText.text += string.Format("\nSuccessfully imported \"{0}\" anchors.", anchorBatch.anchorCount.ToString());
    }
    //for infinitely looking for anchors:
    //if (anchorBatch.anchorCount == 0)
    //{
    // AnchorDebugText.text += string.Format("\nTrying again!");
    // WorldAnchorTransferBatch.ImportAsync(rawAnchorDownloadData, ImportComplete);
    //}

    ////////////////////the code that triggers the anchor import, I assume:

    ` protected override void Update()
    {
    if (AnchorStore == null ||
    SharingStage.Instance == null ||
    SharingStage.Instance.CurrentRoom == null ||
    !canUpdate)
    { return; }

            if (LocalAnchorOperations.Count > 0)
            {
                if (!isExportingAnchors && !isImportingAnchors)
                {
                    DoAnchorOperation(LocalAnchorOperations.Dequeue());
                }
            }
            else
            {
                if (shouldImportAnchors && !isImportingAnchors && !isExportingAnchors)
                {
                    if (AnchorDebugText != null)
                    {
                        AnchorDebugText.text += "\nStarting Anchor Download...";
                    }
    
                    isImportingAnchors = true;
                    shouldImportAnchors = false;
                   ** WorldAnchorTransferBatch.ImportAsync(rawAnchorDownloadData, ImportComplete);**
                }
    
                if (shouldExportAnchors && !isExportingAnchors && !isImportingAnchors)
                {
                    if (AnchorDebugText != null)
                    {
                        AnchorDebugText.text += "\nStarting Anchor Upload...";
                    }
    
                    isExportingAnchors = true;
                    shouldExportAnchors = false;
                    WorldAnchorTransferBatch.ExportAsync(currentAnchorTransferBatch, WriteBuffer, ExportComplete);
                }
    
            }
        }`
    
  • Hi all,
    thanks for the useful information. In my project, I also have to import the anchors properly, that is why, I would like to trigger the import with a button again and again until it is successful.. But I am not sure which part of the code is starting the import and how can I do it. I tired to change SharingWorldAnchorManager.cs exactly the place it gives "Succesfully imported 0 anchors" debug text as you can see below with the commented out part.

    I would appreciate if someone could lead me to the right direction to understand how to trigger import properly..

    Thanks in advance.

        private void ImportComplete(SerializationCompletionReason status, WorldAnchorTransferBatch anchorBatch)
            {
                bool successful = status == SerializationCompletionReason.Succeeded;
                GameObject objectToAnchor = null;
                if (successful)
                {
                    if (ShowDetailedLogs)
                    {
                        Debug.LogFormat("[SharingWorldAnchorManager] Successfully imported \"{0}\" anchors.", anchorBatch.anchorCount.ToString());
                    }
    
                    if (AnchorDebugText != null)
                    {
                        AnchorDebugText.text += string.Format("\nSuccessfully imported \"{0}\" anchors.", anchorBatch.anchorCount.ToString());
                    }
                    //for infinitely looking for anchors:
                    //if (anchorBatch.anchorCount == 0)
                    //{
                    //    AnchorDebugText.text += string.Format("\nTrying again!");
                    //    WorldAnchorTransferBatch.ImportAsync(rawAnchorDownloadData, ImportComplete);
                    //}
    
    
                    string[] anchorNames = anchorBatch.GetAllIds();
    
                    for (var i = 0; i < anchorNames.Length; i++)
                    {
                        if (AnchorGameObjectReferenceList.TryGetValue(anchorNames[i], out objectToAnchor))
                        {
                            AnchorStore.Save(anchorNames[i], anchorBatch.LockObject(anchorNames[i], objectToAnchor));
                        }
                        else
                        {
                            //TODO: Figure out how to get the GameObject reference from across the network.  For now it's best to use unique GameObject names.
                            Debug.LogWarning("[SharingWorldAnchorManager] Unable to import anchor!  We don't know which GameObject to anchor!");
    
                            if (AnchorDebugText != null)
                            {
                                AnchorDebugText.text += "\nUnable to import anchor!  We don\'t know which GameObject to anchor!";
                                //AnchorDebugText.text += string.Format("\nTrying again!");
                                //WorldAnchorTransferBatch.ImportAsync(rawAnchorDownloadData, ImportComplete);
                            }
                        }
                    }
                }
                else
                {
                    Debug.LogError("[SharingWorldAnchorManager] Import failed!");
    
                    if (AnchorDebugText != null)
                    {
                        AnchorDebugText.text += "\nImport failed!";
                        
                        //trying infinitely
                        //AnchorDebugText.text += string.Format("\nTrying again!");
                        //WorldAnchorTransferBatch.ImportAsync(rawAnchorDownloadData, ImportComplete);
                        
                    }
                }
    
                if (AnchorDownloaded != null)
                {
                    AnchorDownloaded(successful, objectToAnchor);
                }
    
                anchorBatch.Dispose();
                rawAnchorDownloadData = null;
                isImportingAnchors = false;
            }
    
Sign In or Register to comment.