Unity Marker¶
Introduction¶
Trackable Marker is a feature which facilitates the development of Mixed Reality applications by tracking external markers detected by the device.
Note
The Trackable Marker feature is current in Beta.
Contents |
Prerequisite¶
- In Unity Editor, go to Project Settings -> Wave XR -> Essence to import the Trackable Marker feature pack.
- You have to add below declaration to your AndroidManifest.xml to enable Trackable Marker.
<uses-feature android:name="wave.feature.marker" android:required="true" />
You can also select Project Settings > XR Plug-in Management > WaveXRSettings > Marker > Enable Marker, which will add the above declaration to the AndroidManifest.xml automatically.
How to use¶
- Add a
TrackableMarkerController
Component to a GameObject in your scene. - Assign a GameObject reference which represents the Tracking Origin as it will be needed for pose correction.
- Use the APIs and helper functions provided by
TrackableMarkerController
to start using Trackable Marker.
Note
To call the APIs and helper functions provided by TrackableMarkerController
, add the Wave.Native
and Wave.Essence.TrackableMarker
namespaces to your script.
In the following sections, we will be referring to sample code which are simplified excerpts from the demo scripts which can be found in the imported feature pack resources in Assets/Wave/Essence/TrackableMarker/<version>/Demo/Scripts.
Marker Service and Observer¶
To start using Trackable Marker, you have to first start the marker service and observer:
- Call
trackableMarkerController.StartMarkerService()
to initialize the resources required to start using Trackable Marker. - Call
trackableMarkerController.StartMarkerObserver()
to start the observer which will be necessary for detecting and tracking markers. - Call other APIs and helper functions related to the Trackable Marker feature.
- Call
trackableMarkerController.StopMarkerObserver()
to stop the observer when you no longer need to detect or track markers. - Call
trackableMarkerController.StopMarkerService()
once you have finished using Trackable Marker.
//Sample code that leverages Unity MonoBehavior lifecycle for starting and stopping Trackable Marker Service and Observer
public TrackableMarkerController trackableMarkerController = null; //Trackable marker controller reference
public bool isMarkerServiceRunning = false, isMarkerObserverRunning = false; //booleans for keeping track of the state of the Marker Service and Observer
private WVR_MarkerObserverTarget currentMarkerObserverTarget = WVR_MarkerObserverTarget.WVR_MarkerObserverTarget_Aruco; //Target marker type to be observed
public void OnEnable()
{
//Check whether feature is supported on device or not
if ((Interop.WVR_GetSupportedFeatures() & (ulong)WVR_SupportedFeature.WVR_SupportedFeature_Marker) != 0)
{
WVR_Result result = trackableMarkerController.StartMarkerService();
if (result == WVR_Result.WVR_Success)
{
isMarkerServiceRunning = true;
StartMarkerObserver();
}
}
}
public void OnDisable()
{
if (!isMarkerServiceRunning) return;
StopMarkerObserver();
trackableMarkerController.StopMarkerService();
isMarkerServiceRunning = false;
}
public void StartMarkerObserver()
{
if (isMarkerServiceRunning && !isMarkerObserverRunning)
{
WVR_Result result = trackableMarkerController.StartMarkerObserver(currentMarkerObserverTarget);
if (result == WVR_Result.WVR_Success)
{
isMarkerObserverRunning = true;
}
}
}
public void StopMarkerObserver()
{
if (isMarkerServiceRunning && isMarkerObserverRunning)
{
WVR_Result result = trackableMarkerController.StopMarkerObserver(currentMarkerObserverTarget);
if (result == WVR_Result.WVR_Success)
{
isMarkerObserverRunning = false;
}
}
}
Observer related enum definitions as follows:
//Basic overview of observer enum definitions
public enum WVR_MarkerObserverTarget
{
WVR_MarkerObserverTarget_Aruco = 0,
WVR_MarkerObserverTarget_Max = 0x7FFFFFFF
}
public enum WVR_MarkerObserverState
{
WVR_MarkerObserverState_Idle = 0, //Observer is in idle state
WVR_MarkerObserverState_Detecting = 1, //Detecting surrounding markers
WVR_MarkerObserverState_Tracking = 2, //Tracking created trackable markers
WVR_MarkerObserverState_Max = 0x7FFFFFFF
}
Detecting, Creating and Tracking Trackable Markers¶
Markers have to be detected before they can be tracked. Assuming that you have started the marker service and observer successfully, follow these tips to detect, create and track trackable markers:
- Call
trackableMarkerController.StartMarkerDetection()
to start detecting markers. - When observer state of the target marker type is
WVR_MarkerObserverState.WVR_MarkerObserverState_Detecting
, you can call APIs to retrieve the detected markers, e.g. For Aruco Markers, calltrackableMarkerController.GetArucoMarkers()
to get all the detected Aruco Markers. - To create trackable markers from detected markers, call
trackableMarkerController.CreateTrackableMarker()
with the uuid of a detected marker as parameter. - After creating the trackable markers you need, call
trackableMarkerController.StopMarkerDetection()
to stop detecting markers. - To retrieve all uuids of the Trackable Markers of a target type, call
trackableMarkerController.GetTrackableMarkers()
. - To start tracking a Trackable Marker, call
trackableMarkerController.StartTrackableMarkerTracking()
with the uuid of the trackable marker as parameter. - To get the state of a Trackable Marker, call
trackableMarkerController.GetTrackableMarkerState()
. You can also get data of a trackable marker specific to its type, e.g. For Aruco Markers, calltrackableMarkerController.GetArucoMarkerData()
. - To stop tracking a Trackable Marker, call
trackableMarkerController.StopTrackableMarkerTracking()
with the uuid of the trackable marker as parameter. - To destroy a trackable marker, call
trackableMarkerController.DestroyTrackableMarker()
with the uuid of a trackable marker as parameter. - To destroy all trackable marker, call
trackableMarkerController.ClearTrackableMarkers()
. - You can use the helper function
TrackableMarkerController.IsUUIDEqual()
for comparing the uuid of the markers. - You can use the helper function
trackableMarkerController.ApplyTrackingOriginCorrectionToMarkerPose()
to convert the pose of a marker to world space position and rotation that are usable in the Unity coordinate system.
//Sample Code for detecting markers
private WVR_MarkerObserverState currentMarkerObserverState = WVR_MarkerObserverState.WVR_MarkerObserverState_Idle; //State of the observer
private WVR_MarkerObserverTarget currentMarkerObserverTarget = WVR_MarkerObserverTarget.WVR_MarkerObserverTarget_Aruco; //Observed target marker type
public void StartMarkerDetection()
{
WVR_Result result = trackableMarkerController.StartMarkerDetection(markerObserverTarget);
if (result == WVR_Result.WVR_Success)
{
//Marker detection started successfully
}
}
public void StopMarkerDetection()
{
WVR_Result result = trackableMarkerController.StopMarkerDetection(markerObserverTarget);
if (result == WVR_Result.WVR_Success)
{
//Marker detection stopped successfully
}
}
public void Update()
{
//Check whether observer is in detection state or not
WVR_Result result = trackableMarkerController.GetMarkerObserverState(currentMarkerObserverTarget, out currentMarkerObserverState);
if (result == WVR_Result.WVR_Success)
{
if (currentMarkerObserverState == WVR_MarkerObserverState.WVR_MarkerObserverState_Detecting)
{
//Observer in detection state, retrieved detected markers and create trackable markers if needed
}
}
}
//Sample Code for creating/destroying trackable markers
public void CreateTrackableMarker(WVR_Uuid targetMarkerId, WVR_MarkerObserverTarget observerTarget)
{
string markerNameString = BitConverter.ToString(targetMarkerId.data); //As an example, we use the uuid of the marker as marker name
char[] markerNameCharArray = markerNameString.ToCharArray();
WVR_Result result = trackableMarkerController.CreateTrackableMarker(targetMarkerId, markerNameCharArray);
if (result == WVR_Result.WVR_Success)
{
//Trackable Marker created successfully
}
}
public void DestroyTrackableMarker(WVR_Uuid targetMarkerId)
{
WVR_Result result = trackableMarkerController.DestroyTrackableMarker(targetMarkerId);
if (result == WVR_Result.WVR_Success)
{
//Trackable Marker destroyed successfully
}
}
//Sample Code for tracking and get the state of trackable markers
public void StartTrackingTrackableMarkers(WVR_Uuid targetMarkerId)
{
WVR_Result result = trackableMarkerController.StartTrackingTrackableMarkers(targetMarkerId);
if (result == WVR_Result.WVR_Success)
{
//Trackable Marker is tracked
}
}
public void StopTrackingTrackableMarkers(WVR_Uuid targetMarkerId)
{
WVR_Result result = trackableMarkerController.StopTrackingTrackableMarkers(targetMarkerId);
if (result == WVR_Result.WVR_Success)
{
//Trackable Marker is no longer tracked
}
}
public void GetTrackableMarkerState(WVR_Uuid targetMarkerId, out WVR_TrackableMarkerState markerState)
{
markerState = default(WVR_TrackableMarkerState);
WVR_Result result = trackableMarkerController.GetTrackableMarkerState(targetMarkerId, TrackableMarkerController.GetCurrentPoseOriginModel(), out markerState);
if (result == WVR_Result.WVR_Success)
{
//state of Trackable Marker retrieved successfully
}
}
As for the data of markers, you can refer to the struct and enum definitions as follows:
//Basic overview of marker data
public struct WVR_ArucoMarker
{
public WVR_Uuid uuid; //Uuid of the marker
public UInt64 trackerId; //Marker id of the Aruco Marker
public float size; //Size of the Aruco Marker
public WVR_MarkerTrackingState state; //Tracking state of the marker
public WVR_Pose_t pose; //Pose of the marker
public WVR_MarkerName markerName; //Name of the marker (Set when designated as a trackable marker)
}
public struct WVR_TrackableMarkerState
{
public WVR_MarkerObserverTarget target; //Target type of the marker
public WVR_MarkerTrackingState state; //Tracking state of the marker
public WVR_Pose_t pose; //Pose of the marker
public WVR_MarkerName markerName; //Name of the marker
}
public struct WVR_ArucoMarkerData
{
public UInt64 trackerId; //Marker id of the Aruco Marker
public float size; //Size of the Aruco Marker
}
public struct WVR_MarkerName
{
public char[] name; //Limited to 256 characters (including null terminating character)
}
public enum WVR_MarkerTrackingState
{
WVR_MarkerTrackingState_Detected,
WVR_MarkerTrackingState_Tracked,
WVR_MarkerTrackingState_Paused,
WVR_MarkerTrackingState_Stopped
}
Other Useful Functions¶
Other than the ones mentioned in this tutorial, there are still other APIs and functions that might be useful to you that are not explained in this documentation.
You can find the details on the APIs and helper functions in the form of XML API documentation in the TrackableMarkerController
script.
Resources¶
The imported resources of the Trackable Marker Feature Pack can be found in Assets/Wave/Essence/TrackableMarker.
Points to take note of and Known Issues¶
- Trackable Markers are tied to the active tracking map when they are created. Changing the active tracking map will result in the loss of Trackable Markers that exist in the previous tracking map(s).