Marker pose rotation value differ even if the QR place in the same location

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?

Do you mind providing some information about the data that you have embedded in the QR Code? How many characters are you adding to the marker?

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.
image
image

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.