How to use ArAnchor to track imageTarget position after it is lost?

Hi,

i try to keep tracking the last known position of an imageTarget by creating an ArAnchor at the position of the imageTarget, but i can not get it to work right.

I found a workaround, which you can see in the following code, but this is a bad solution and i would like to avoid using this workaround.

i did simply extend the class AnchorCreator of the arfoundation samples to make a small test project. I added the class in the code below as well as an ArTrackedImageManager to the Anchors scene in the samples.

The problem is, that i want to create a new Pose at the imageTarget transforms position, but if i do so with

Pose newPose = new Pose(trackedImage.transform.position, trackedImage.transform.rotation);
``` it is returning a different Pose than if i do a raycast to the plane represented by the image. It seems, that the returned Pose of the Raycast is in a different coordinate system (maybe ARSpace). The raycast workaround is only working if the tracked image is known to be vertical or horizontally placed and if a plane is found and that is not always the case if an image is found. There should be a way to create a correct Pose for a trackedImageTarget without doing a raycast, that could also fail.

I would appreciate any help.

TestCode

[spoiler]

```csharp
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;

[RequireComponent(typeof(ARAnchorManager))]
[RequireComponent(typeof(ARRaycastManager))]
[RequireComponent(typeof(ARTrackedImageManager))]
public class AnchorCreatorImageTracking : MonoBehaviour
{
    public void RemoveAllAnchors()
    {
        foreach (var anchor in m_Anchors)
        {
            m_AnchorManager.RemoveAnchor(anchor);
        }
        m_Anchors.Clear();
    }

    void Awake()
    {
        m_RaycastManager = GetComponent<ARRaycastManager>();
        m_AnchorManager = GetComponent<ARAnchorManager>();
        m_TrackedImageManager = GetComponent<ARTrackedImageManager>();

        m_TrackedImageManager.trackedImagesChanged += OnTrackedImagesChanged;
        m_Anchors = new List<ARAnchor>();
    }

    void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs)
    {
        foreach (var trackedImage in eventArgs.added)
        {
            Pose newPose = new Pose(trackedImage.transform.position, trackedImage.transform.rotation);

            if (m_RaycastManager.Raycast( Camera.main.WorldToScreenPoint(trackedImage.transform.position), s_Hits, TrackableType.Planes))
            {
                Debug.Log("onFound HitTest PLanes");
                Debug.LogFormat("HitTest Pose position: {0} rotation: {1}",s_Hits[0].pose.position,s_Hits[0].pose.rotation);
                Debug.LogFormat("TrackedImage position: {0} rotation: {1}",trackedImage.transform.position,trackedImage.transform.rotation);
                Debug.LogFormat("TrackedImage localPosition: {0} localRotation: {1}",trackedImage.transform.localPosition,trackedImage.transform.localRotation);
                var hitPose = s_Hits[0].pose;
                var anchor = m_AnchorManager.AddAnchor(hitPose);
                m_Anchors.Add(anchor);
            }
         
            var anchor2 = m_AnchorManager.AddAnchor(newPose);        
            m_Anchors.Add(anchor2);
         
        }

    }

    void Update()
    {
        if (Input.touchCount == 0)
            return;

        var touch = Input.GetTouch(0);
        if (touch.phase != TouchPhase.Began)
            return;

        if (m_RaycastManager.Raycast(touch.position, s_Hits, TrackableType.FeaturePoint))
        {
            // Raycast hits are sorted by distance, so the first one
            // will be the closest hit.
            var hitPose = s_Hits[0].pose;
            var anchor = m_AnchorManager.AddAnchor(hitPose);
            if (anchor == null)
            {
                Logger.Log("Error creating anchor");
            }
            else
            {
                m_Anchors.Add(anchor);
            }
        }
    }

    static List<ARRaycastHit> s_Hits = new List<ARRaycastHit>();

    List<ARAnchor> m_Anchors;

    ARRaycastManager m_RaycastManager;

    ARAnchorManager m_AnchorManager;

    ARTrackedImageManager m_TrackedImageManager;
}

[/spoiler]

ok i found my problem. In case someone have the same problem. The specified marker size in ARFoundation has to match the real image target size exactly. If that is the case the code is working as expected Pose newPose = new Pose(trackedImage.transform.position, trackedImage.transform.rotation);
I still have no solution if you want to use the same marker with a different size.

for my use case it worked best to create the marker some frames after it was initially found and not on lost. so i used the marker only for initial positioning of the Ar Anchor.

1 Like

Hi there. Im really trying to use Anchors for image tracking also. I can see you create a new Pose… But I am struggling with the rest. The new component for ArAnchors has me confused as to how to create an anchor and then add my content to it?

cheers.