I am currently using ARCore for real-time image tracking, and I am facing an issue where the tracking status of an object does not reset even when I am no longer pointing the camera at the tracked image.
Issue Description:
- I have implemented image tracking using ARCore’s Augmented Image Database.
- When an object gets successfully detected and tracked, it maintains the TrackingState.TRACKING status as expected.
- However, the issue arises when I move the camera away from the tracked object. Instead of switching to TrackingState.PAUSED or stopping tracking, it continues to show the object as “tracked” even though it is no longer in the camera’s view.
- This causes unintended behavior, as the app still considers the object as detected and tracked, even though it is no longer visible in the frame.
ARCore Dependencies:
core = "1.47.0"
core = { module = "com.google.ar:core", version.ref = "core" }
sceneformUx = "1.17.1"
sceneform-ux = { group = "com.google.ar.sceneform.ux", name = "sceneform-ux", version.ref = "sceneformUx" }
AR SceneView XML:
<fragment
android:id="@+id/ar_scene_view"
android:name="com.google.ar.sceneform.ux.ArFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
ARCore Initialization:
private lateinit var arFragment: ArFragment
arFragment = supportFragmentManager.findFragmentById(R.id.ar_scene_view) as ArFragment
private fun initializeAR() {
var exception: Exception? = null
try {
when (ArCoreApk.getInstance().requestInstall(this, true)) {
ArCoreApk.InstallStatus.INSTALLED -> setupSession()
ArCoreApk.InstallStatus.INSTALL_REQUESTED -> return
}
} catch (e: Exception) {
exception = e
}
if (exception != null || arSession == null) {
Toast.makeText(this, "ARCore failed to initialize", Toast.LENGTH_LONG).show()
finish()
}
}
Session Setup for Image Tracking:
private fun setupSession() {
arFragment.planeDiscoveryController.hide()
arFragment.planeDiscoveryController.setInstructionView(null)
arSession = Session(this)
arConfig = Config(arSession)
setupImageDatabase {
arConfig?.setAugmentedImageDatabase(augmentedImageDatabase)
arSession?.configure(arConfig)
handler.post { Toast.makeText(this, "Database Sync Completed", Toast.LENGTH_SHORT).show() }
}
arConfig?.setFocusMode(Config.FocusMode.AUTO)
arConfig?.planeFindingMode = Config.PlaneFindingMode.DISABLED
arConfig?.imageStabilizationMode = Config.ImageStabilizationMode.OFF
arConfig?.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE)
arSession?.configure(arConfig)
arFragment.arSceneView?.setupSession(arSession)
}
Frame Update to Track Images:
override fun onUpdate(frameTime: FrameTime?) {
val frame = arFragment.arSceneView?.arFrame ?: return
val images = frame.getUpdatedTrackables(AugmentedImage::class.java)
for (image in images) {
when (image.trackingState) {
TrackingState.TRACKING -> {
if (!trackedImages.contains(image.name)) {
handleDetectedImage(image)
trackedImages.add(image.name)
}
}
TrackingState.PAUSED -> {
// Remove tracking if the image is no longer visible
trackedImages.remove(image.name)
runOnUiThread {
Toast.makeText(this, "Tracking lost for ${image.name}", Toast.LENGTH_SHORT).show()
}
}
TrackingState.STOPPED -> {
// Clear the image from tracking
trackedImages.remove(image.name)
}
}
}
}
- Verified that I am properly updating and listening to the TrackingState in the frame update loop.
- Ensured that the Augmented Image Database is correctly initialized and that images are of high quality.
- Tried resetting the session or reloading the database when tracking fails, but the issue persists.
- Checked ARCore documentation and Stack Overflow, but could not find a concrete solution for this behavior.
override fun onUpdate(frameTime: FrameTime?) {
val frame = arFragment.arSceneView?.arFrame ?: return
val images = frame.getUpdatedTrackables(AugmentedImage::class.java)
for (image in images) {
when (image.trackingState) {
TrackingState.TRACKING -> {
if (!trackedImages.contains(image.name)) {
handleDetectedImage(image)
trackedImages.add(image.name)
}
}
TrackingState.PAUSED -> {
// Remove tracking if the image is no longer visible
trackedImages.remove(image.name)
runOnUiThread {
Toast.makeText(this, "Tracking lost for ${image.name}", Toast.LENGTH_SHORT).show()
}
}
TrackingState.STOPPED -> {
// Clear the image from tracking
trackedImages.remove(image.name)
}
}
}
}
Expected Behavior:
- When the camera is no longer pointing at the tracked image, the TrackingState should change to PAUSED or STOPPED instead of remaining in the TRACKING state.