Hi folks,
I am trying to detect a marker and wanted to aligned the CAD model to the marker.
However, the model is not properly aligned with the marker. To troubleshoot, I checked the rotation values using the following script:
// Store the initial pose
_initialMarkerPoseById[id] = data.MarkerPose.Value;
// Get the rotation
Quaternion rotation = _initialMarkerPoseById[id].rotation;
XValueRx.text = rotation.eulerAngles.x.ToString();
YValueRy.text = rotation.eulerAngles.y.ToString();
ZValueRz.text = rotation.eulerAngles.z.ToString();
The detected marker's rotation values do not match the previous ones,
even if the marker's (QR code) posture remains the same.
How is the marker pose value extracted in Magic Leap 2?
What is the procedure to get consistent marker rotation values with the marker being kept in the same place?
I have been using some random QR code (QR code of a Vuforia experience), so I don't know how many characters are within it. Is there any limit of the number of characters that can be added to the marker? How can I create a QR code that can be used for Magic Leap 2 Marker Tracking ?
I tried with ArUco code too with the following code. Still the model cannot be aligned properly with the marker.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.OpenXR;
using MagicLeap.OpenXR.Features.MarkerUnderstanding;
using System.Linq;
public class MarkerTrackingTest : MonoBehaviour
{
[Tooltip("The GameObject that will be moved to the position of the detected marker.")]
public GameObject TargetObject;
[SerializeField] private float moveDistance = 1.0f; // distance to move
public ArucoType ArucoType = ArucoType.Dictionary_5x5_50;
public MarkerDetectorProfile DetectorProfile = MarkerDetectorProfile.Default;
private MarkerDetectorSettings _detectorSettings;
private MagicLeapMarkerUnderstandingFeature _markerFeature;
private readonly Dictionary<string, Pose> _initialMarkerPoseById = new Dictionary<string, Pose>();
private void Start()
{
_markerFeature = OpenXRSettings.Instance.GetFeature<MagicLeapMarkerUnderstandingFeature>();
if (_markerFeature == null || _markerFeature.enabled == false)
{
Debug.LogError("The Magic Leap 2 Marker Understanding OpenXR Feature is missing or disabled. Disabling Script.");
this.enabled = false;
return;
}
// Create the Marker Detector Settings
_detectorSettings = new MarkerDetectorSettings();
// Configure a generic detector with QR and Aruco Detector settings
_detectorSettings.QRSettings.EstimateQRLength = true;
_detectorSettings.ArucoSettings.EstimateArucoLength = true;
_detectorSettings.ArucoSettings.ArucoType = ArucoType;
_detectorSettings.MarkerDetectorProfile = DetectorProfile;
// Create Aruco detector
_detectorSettings.MarkerType = MarkerType.Aruco;
_markerFeature.CreateMarkerDetector(_detectorSettings);
// Create QRCode Detector
_detectorSettings.MarkerType = MarkerType.QR;
_markerFeature.CreateMarkerDetector(_detectorSettings);
// Create UPCA Detector
_detectorSettings.MarkerType = MarkerType.UPCA;
_markerFeature.CreateMarkerDetector(_detectorSettings);
}
private void OnDestroy()
{
if (_markerFeature != null)
{
_markerFeature.DestroyAllMarkerDetectors();
}
}
void Update()
{
// Update the marker detector
_markerFeature.UpdateMarkerDetectors();
// Iterate through all of the marker detectors
for (int i = 0; i < _markerFeature.MarkerDetectors.Count; i++)
{
// Verify that the marker detector is running
if (_markerFeature.MarkerDetectors[i].Status == MarkerDetectorStatus.Ready)
{
// Cycle through the detector's data and log it to the debug log
MarkerDetector currentDetector = _markerFeature.MarkerDetectors[i];
OnUpdateDetector(currentDetector);
// If a marker is detected, stop further processing
if (_initialMarkerPoseById.Count > 0)
{
break;
}
}
}
}
private void OnUpdateDetector(MarkerDetector detector)
{
for (int i = 0; i < detector.Data.Count; i++)
{
string id = "";
float markerSize = 0.18f;
var data = detector.Data[i];
switch (detector.Settings.MarkerType)
{
case MarkerType.Aruco:
id = data.MarkerNumber.ToString();
markerSize = data.MarkerLength;
break;
case MarkerType.QR:
id = data.MarkerString;
markerSize = data.MarkerLength;
break;
case MarkerType.UPCA:
Debug.Log("No pose is given for marker type UPCA, Code value is " + data.MarkerString);
break;
}
if (!data.MarkerPose.HasValue)
{
Debug.Log("Marker Pose not estimated yet.");
return;
}
if (!string.IsNullOrEmpty(id) && markerSize > 0)
{
// If any marker is already tracked, skip this one
if (_initialMarkerPoseById.Count > 0)
{
return;
}
// Store the initial pose
_initialMarkerPoseById[id] = data.MarkerPose.Value;
// Move the target object to the marker's position
SetTransformToMarkerPose(TargetObject.transform, data.MarkerPose.Value);
}
}
}
private void SetTransformToMarkerPose(Transform target, Pose markerPose)
{
// Directly set the target's position and rotation to the detected pose
target.position = markerPose.position;
target.rotation = markerPose.rotation;
// Apply an additional 90-degree rotation around the x-axis
// The CAD source Up vector is Z-axis
Quaternion additionalRotation = Quaternion.Euler(-90, 0, 0);
target.rotation = target.rotation * additionalRotation;
}
This is my hierarchy and corresponding inspection panel of the model that has to be aligned with the marker.
I asked about the QR code because the amount of data on a QR code can affect the quality of the tracking. For instance if you have a QR code that has a single character encoded into it.
But based on your description you might be running into a different type of issue.
Are you experiencing an issue with the marker pose being too far or too close relative to the marker or is the main issue the stability of the marker's rotation? Does this behavior happen when you stand still or only as you move around ?
Would it be possible to ask you for a video of the issue you are seeing?
Note: Before recording the video please enable the OpenXR Magic Leap Secondary View feature in the project settings to improve the alignment of the virtual content when performing Mixed Reality Capture.