Topic locked

How do you switch database (2021) programmatically

November 2, 2021 - 1:40pm #1

How do you programmatically switch databases? This seems to have been answered in the past, but the solutions do not work for 2021. 

 

 

public void SwitchDB(string dataSetName)
    {
     //   TrackerManager trackerManager = (TrackerManager)TrackerManager.Instance;
        ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();
        IEnumerable datasets = objectTracker.GetDataSets();
        IEnumerable activeDataSets = objectTracker.GetActiveDataSets();
        //  List activeDataSetsToBeRemoved = activeDataSets.ToList();

        //Loop through all the active datasets and deactivate them.
        foreach (DataSet ads in activeDataSets)
        {
            objectTracker.DeactivateDataSet(ads);
        }


        foreach (TrackableBehaviour tb in itb)
        {
            Destroy(tb.gameObject);
        }
         
        DataSet dataSet = objectTracker.CreateDataSet();

        if (dataSet.Load(dataSetName))
        {
            objectTracker.Stop();  // stop tracker so that we can add new dataset

            if (!objectTracker.ActivateDataSet(dataSet))
            {
                // Note: ImageTracker cannot have more than 100 total targets activated
                Debug.Log("Failed to Activate DataSet: " + dataSetName + "");
            }

            if (!objectTracker.Start())
            {
                Debug.Log("Tracker Failed to Start.");
            }
             
            FindITB();
        }
    }

    // finds image targets created and 
    public void FindITB()
    {
        itb = TrackerManager.Instance.GetStateManager().GetTrackableBehaviours();

        foreach (TrackableBehaviour tb in itb)
        {
            tb.gameObject.AddComponent();
            CreatedImageTargetBehaviour citb = tb.gameObject.GetComponent();
            citb.StatusFilter = CreatedImageTargetBehaviour.TrackingStatusFilter.Tracked;
            
            tb.name = tb.TrackableName;
        }
    }

If there is an existing ImageTarget in the scene, it seems that the database would not be switched in the ImageTargetBehaviour. In addition, it doesn't appear to be a way to programmatically switch that database (?)

Leads to errors like

InvalidOperationException: Collection was modified; enumeration operation may not execute.
System.ThrowHelper.ThrowInvalidOperationException (System.ExceptionResource resource) (at :0)
System.Collections.Generic.List`1+Enumerator[T].MoveNextRare () (at :0)
System.Collections.Generic.List`1+Enumerator[T].MoveNext () (at :0)
CreateTargetsFromDB.SwitchDB (System.String dataSetName) (at

How do you switch database (2021) programmatically

December 31, 2021 - 1:19am #7

I am glad I have found your post, I was searching for it for my friend. 

How do you switch database (2021) programmatically

November 10, 2021 - 1:33pm #6

Hi @medabit 

 

I think I followed that example from a previous thread someone else posted. However, it does not include directions for how to properly remove previously created Image Target gameobjects from the previous dataset.  I have tried swapping the order around, such as destroy before stop or stop before destroy, but the reflection error occurs below each time:

 

Exception in callback: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> UnityEngine.MissingReferenceException: The object of type 'ImageTargetBehaviour' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
  at (wrapper managed-to-native) UnityEngine.Behaviour.get_enabled(UnityEngine.Behaviour)
  at Vuforia.StateManager+c.b__29_0 (Vuforia.TrackableBehaviour b) [0x00000] in :0 
  at System.Linq.Enumerable+WhereEnumerableIterator`1[TSource].MoveNext () [0x00037] in :0 
  at Vuforia.StateManager.UpdateTrackableStates (Vuforia.TrackerData+TrackableResultData[] trackableResults) [0x00106] in :0 
  at Vuforia.StateManager.UpdateTrackablePoses (UnityEngine.Vector3 positionalOffset, UnityEngine.Quaternion rotationalOffset, Vuforia.TrackerData+TrackableResultData[] trackableResultDataArray, Vuforia.TrackerData+VuMarkTargetResultData[] vuMarkResultDataArray, Vuforia.VuforiaManager+TrackableIdPair originTrackableID, System.Int32 frameIndex, System.Boolean updateTrackableStates) [0x000e3] in :0 
  at Vuforia.StateManager.UpdateTrackablePoses (UnityEngine.Vector3 positionalOffset, UnityEngine.Quaternion rotationalOffset, Vuforia.TrackerData+TrackableResultData[] trackableResultDataArray, Vuforia.TrackerData+VuMarkTargetResultData[] vuMarkResultDataArray, Vuforia.VuforiaManager+TrackableIdPair originTrackableID, System.Int32 frameIndex) [0x00000] in :0 
  at Vuforia.VuforiaManager.UpdateTrackers (Vuforia.TrackerData+ManagedFrameState frameState) [0x002c2] in :0 
  at Vuforia.VuforiaManager.Update (Vuforia.VuforiaScreenOrientation counterRotation, System.Boolean& reapplyOldState) [0x0005e] in :0 
  at Vuforia.VuforiaARController.UpdateStatePrivate (System.Boolean forceUpdate, System.Boolean reapplyOldState) [0x00051] in :0 
  at Vuforia.VuforiaARController.UpdateState (System.Boolean forceUpdate, System.Boolean reapplyOldState) [0x0000c] in :0 
  at Vuforia.DigitalEyewearARController.Update () [0x00000] in :0 
  at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&)
  at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in :0 
   --- End of inner exception stack trace ---
  at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00048] in :0 
  at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in :0 
  at System.Delegate.DynamicInvokeImpl (System.Object[] args) [0x000e7] in :0 
  at System.MulticastDelegate.DynamicInvokeImpl (System.Object[] args) [0x00008] in :0 
  at System.Delegate.DynamicInvoke (System.Object[] args) [0x00000] in :0 
  at Vuforia.DelegateHelper.InvokeDelegate (System.Delegate action, System.Object[] args) [0x0000f] in :0 
UnityEngine.Debug:LogError (object)
Vuforia.DelegateHelper:InvokeDelegate (System.Delegate,object[])
Vuforia.DelegateHelper:InvokeWithExceptionHandling (System.Action)
Vuforia.VuforiaBehaviour:Update ()

 

    void LoadDataSet(string dataSetName)
    {
        

        ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();

        DataSet dataSet = objectTracker.CreateDataSet();

        if (dataSet.Load(dataSetName))
        {
             

           
            objectTracker.Stop();  // stop tracker so that we can add new dataset

            if (itb != null)
                foreach (TrackableBehaviour tb in itb)
                { Destroy(tb.gameObject); }

            if (!objectTracker.ActivateDataSet(dataSet))
            {
                // Note: ImageTracker cannot have more than 100 total targets activated
                Debug.Log("Failed to Activate DataSet: " + dataSetName + "");
            }

            if (!objectTracker.Start())
            {
                Debug.Log("Tracker Failed to Start.");
            }
             
            FindITB();
        }
        else
        {
            Debug.LogError("Failed to load dataset: '" + dataSetName + "'");
        }
    }

    // finds image targets created and 
    void FindITB()
    {
        itb = TrackerManager.Instance.GetStateManager().GetTrackableBehaviours();

        foreach (TrackableBehaviour tb in itb)
        {
            tb.gameObject.AddComponent();
            CreatedImageTargetBehaviour citb = tb.gameObject.GetComponent();
            citb.StatusFilter = CreatedImageTargetBehaviour.TrackingStatusFilter.Tracked;
            
            tb.name = tb.TrackableName;
        }
    }

How do you switch database (2021) programmatically

November 10, 2021 - 12:15pm #5

Hello,

inayo wrote:

I'm referring to how I cannot seem to designate the Image Target database programmatically. So the snippet creates image target gameobjects programmatically but does not seem to allow for setting the database - so they are the initially activated database 

Understood. Looks like there is an error in the order of operation from your sample code below. The tracker needs to be stopped before you can load and activate a device database. Your code looks to attempt a Load() before stopping the tracker.

Attached is some sample scripts from our Area Targets Test App. Although it is specific to Area Targets, the code is an analogue to show the correct order of operation.

Additionally, we're looking to stand up improved documentation for this very use case.

Thanks,

Vuforia Engine Support

AttachmentSize
Package icon Area Target dataset swap.zip4.58 KB

How do you switch database (2021) programmatically

November 8, 2021 - 10:27pm #4

Once you have loaded a new image target dataset, how do you remove the existing image targets without reflection errors?

 

 

 

I've tried using, where itb is a global that is defined after the targets are created itb = TrackerManager.Instance.GetStateManager().GetTrackableBehaviours();

if (itb != null)
                foreach (TrackableBehaviour tb in itb)
                { Destroy(tb.gameObject); }

This removes the old target gameobjects from the previous database but leads to reflection errors:

Exception in callback: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> UnityEngine.MissingReferenceException: The object of type 'ImageTargetBehaviour' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.

How do you switch database (2021) programmatically

November 5, 2021 - 3:08pm #3

I'm referring to how I cannot seem to designate the Image Target database programmatically. So the snippet creates image target gameobjects programmatically but does not seem to allow for setting the database - so they are the initially activated database 

How do you switch database (2021) programmatically

November 5, 2021 - 9:28am #2

Hello @inayo,

Can you please clarify what you mean by "2021"? Do you mean a 2021 version of Unity? If so, which version?

Nothing has changed in the Engine APIs as Engine 9.8 has been deprecated by 10.X. Thus, unless there has been a regression in Unity (unlikely) this Engine functionality is expected to still work.

Thanks,

Vuforia Engine Support

Topic locked