Log in or register to post comments

Loading/Changing Vumark data set at runtime

February 22, 2017 - 11:26pm #1

Hello.

I am now developing a Vuforia VuMark application which need to swapping between 2 VuMark data set.

The data sets are downloaded from the server for the first load and load it from local for second times. Also, in each database, only 1 VuMark target exists.

However, it seems that I cannot load others data set even I unload the original data set.

Below error ocurred when I try to load the second database.

Could not destroy trackable with id 1.<\p>

Did not load: {Database_Path}\vumark_hololens_db.xml

Here is part of the code.

Test_Main.cpp

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Vuforia;

public class Test_Main : MonoBehaviour
{
    protected static Test_Main instance;

    public string vumarkID = "none";

    public static Test_Main Instance
    {
        get
        {
            if (instance == null)
            {
                instance = (Test_Main)FindObjectOfType(typeof(Test_Main));
                if (instance == null)
                {
                    Debug.LogError("Test_Main is needed.");
                }
            }
            return instance;
        }
    }
   
// Use this for initialization
void Start () {

    }

    public Test_DataSetLoader dataset;

    bool isFirstDataSet = true;

    int frameCount = 0;

    // Update is called once per frame
    void Update () {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StartCoroutine(updateDataSet());
        }
    }

    IEnumerator updateDataSet() {
        yield return new WaitUntil(() => VuforiaRuntimeUtilities.IsVuforiaEnabled());
        yield return new WaitUntil(() => dataset.IsInitialize);

        dataset.UnloadDataSet();
        yield return (dataset.LoadDataSet(isFirstDataSet? 0: 1));
    }
}

Test_DataSetLoader.cpp

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using Vuforia;

public class Test_DataSetLoader : MonoBehaviour {
    private const string BaseURL = "http://{Server_Address}/";
    private static readonly string[] FileTypes = { ".xml", ".dat" };
    private static readonly string[] DatabaseNames = { "vumark_hololens_db", "vumark_hololens_2_db" };

    [SerializeField]
    private VuforiaBehaviour _vuforia = null;

    private DataSet _currentDataSet = null;

    private ObjectTracker tracker = null;

    public bool IsInitialize = false;

    private void Awake()
    {
        Debug.LogFormat("Test_DataSetLoader::Awake()");
        _vuforia.StartEvent += OnVuforiaStart;
    }

    private void OnVuforiaStart()
    {
        Debug.LogFormat("Test_DataSetLoader::OnVuforiaStart()");
        StartCoroutine(Initialize());
    }

    private IEnumerator Initialize()
    {
        Debug.LogFormat("Test_DataSetLoader::Initialize()");
        yield return new WaitUntil(() => VuforiaRuntimeUtilities.IsVuforiaEnabled());

        IsInitialize = true;
        tracker = TrackerManager.Instance.GetTracker();

        Debug.LogFormat("Test_DataSetLoader::Initialize(), Completed");
    }

    public void UnloadDataSet()
    {
        Debug.LogFormat("Test_DataSetLoader::UnloadDataSet()");
        if (_currentDataSet == null)
        {
            return;
        }

        tracker.Stop();

        if (!tracker.DeactivateDataSet(_currentDataSet))
        {
            Debug.LogErrorFormat("Deactive DataSet Error");
        } else
        {
            Debug.LogFormat("Deactive DataSet Success");
        }

        StateManager stateManager = TrackerManager.Instance.GetStateManager();
        foreach (TrackableBehaviour tb in stateManager.GetTrackableBehaviours())
        {
            tb.enabled = false;
            stateManager.DestroyTrackableBehavioursForTrackable(tb.Trackable);
        }

        IEnumerable trackables = _currentDataSet.GetTrackables();
        foreach (Trackable trackable in trackables)
        {
            
            if (_currentDataSet.Destroy(trackable, true))
            {
                Debug.LogFormat("Destroy Trackable: {0}, Success", trackable.Name);
            } else
            {
                Debug.LogErrorFormat("Destroy Trackable: {0}, Fail", trackable.Name);
            }
            TrackerManager.Instance.GetStateManager().DestroyTrackableBehavioursForTrackable(trackable);
            
        }

        if (tracker.DestroyDataSet(_currentDataSet, true))
        {
            Debug.LogFormat("Destroy DataSet Success");
        }
        else
        {
            Debug.LogErrorFormat("Destroy DataSet Fail");
        }

        _currentDataSet = null;

        tracker.Start();
    }

    public IEnumerator LoadDataSet(int DatabaseIndex)
    {
        Debug.LogFormat("Test_DataSetLoader::LoadDataSet()");
        // cache or download
        string filePath = Path.Combine(Application.persistentDataPath, DatabaseNames[DatabaseIndex]);
        
        if (!File.Exists(filePath + FileTypes[0]))
        {
            Debug.LogWarning("Download");
            foreach (var fileType in FileTypes)
            {
                string url = Path.Combine(BaseURL, DatabaseNames[DatabaseIndex]) + fileType;
                using (WWW www = new WWW(url))
                {
                    yield return www;
                    File.WriteAllBytes(filePath + fileType, www.bytes);
                }
            }
        }

        // clear target
        foreach (var row in TrackerManager.Instance.GetStateManager().GetTrackableBehaviours())
        {
            TrackerManager.Instance.GetStateManager().DestroyTrackableBehavioursForTrackable(row.Trackable);
        }

        // create new DataSet
        DataSet dataSet = tracker.CreateDataSet();

        Debug.LogFormat("Test_DataSetLoader::LoadDataSet(), Load Data Set");

        if (!dataSet.Load(filePath + FileTypes[0], VuforiaUnity.StorageType.STORAGE_ABSOLUTE))
        {

            Debug.LogErrorFormat("Load DataSet Error\n{0}", filePath);
            yield break;
        }
        

        tracker.Stop();

        if (!tracker.ActivateDataSet(dataSet))
        {
            Debug.LogErrorFormat("Activate DataSet Error\n{0}", filePath);
            yield break;
        }

        _currentDataSet = dataSet;

        if (!tracker.Start())
        {
            Debug.LogErrorFormat("Restart Tracker Error\n{0}", filePath);
        }
        yield break;
    }
}

Thank you.

Loading/Changing Vumark data set at runtime

February 23, 2017 - 5:05pm #3

medabit wrote:

Hello,

Although your high-level logic is correct, what you're likely experiencing here is a licensing restriction. For any other license key other than Pro, you can only activate a single VuMark database. Although this may not be explicitly apparent, note that the portal workflow only allows you to download a single VuMark template in a database associated with a developer key.

And just to complete the thought, Vuforia does not allow for multiple license keys to be activated in a single app.

Thanks.

So, this means I cannot load and activate another VuMark data set even I unload the original one unless I used the Pro license?

And, am I possible to load a different VuMark data set at the scene begining each time if I reload my Scene?

Loading/Changing Vumark data set at runtime

February 23, 2017 - 12:11pm #2

Hello,

Although your high-level logic is correct, what you're likely experiencing here is a licensing restriction. For any other license key other than Pro, you can only activate a single VuMark database. Although this may not be explicitly apparent, note that the portal workflow only allows you to download a single VuMark template in a database associated with a developer key.

And just to complete the thought, Vuforia does not allow for multiple license keys to be activated in a single app.

Thanks.

Log in or register to post comments