AR Anchor дрейфует или следует за движением камеры в Kotlin/ARCoreAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 AR Anchor дрейфует или следует за движением камеры в Kotlin/ARCore

Сообщение Anonymous »

Постановка проблемы
При размещении якоря AR перед камерой для захвата изображения якорь не остается зафиксированным в физической среде. Вместо этого он сохраняет свое относительное положение относительно устройства, эффективно «следуя» за камерой, когда пользователь перемещает или поворачивает телефон.
Технический контекст
  • Платформа: Android
  • Язык: Kotlin
  • Библиотека: ARCore / Sceneview (укажите, используете ли Sceneform или Filament)
Наблюдаемое поведение
  • Пользователь запускает размещение привязки на определенном расстоянии (например, 1 метр) перед камерой.
  • Изначально привязка отображается правильно.
  • Когда телефон перемещается влево, вправо или вращается, привязка остается привязанной к области просмотра экрана, а не к физическому местоположению GPS или функциональной точки, в которой она была размещена.
Ожидаемое поведение
Якорь должен быть прикреплен к определенной точке координат трехмерного мира. После размещения пользователь должен иметь возможность обойти якорь или отодвинуть камеру от него, п р и э т о м я к о р ь н е и з м е н и т с в о е м и р о в о е п о л о ж е н и е . < / p > < b r / > < h 3 > < s t r o n g > В о з м о ж н ы е п р и ч и н ы д л я и з у ч е н и я < / s t r o n g > < / h 3 > < b r / > < c o d e > < b r / > H E R E m y C O D E ( i n t h i s v e r s i o n I ' v e o n l y i n i t i a l i z e d t h e A R ) < b r / > < b r / > A R S c e n e ( < b r / > m o d i f i e r = s c e n e M o d i f i e r , < b r / > c h i l d N o d e s = c h i l d N o d e s , < b r / > e n g i n e = e n g i n e , < b r / > m o d e l L o a d e r = m o d e l L o a d e r , < b r / > p l a n e R e n d e r e r = p l a n e R e n d e r e r . v a l u e , < b r / > c a m e r a N o d e = c a m e r a N o d e , < b r / > m a t e r i a l L o a d e r = m a t e r i a l L o a d e r , < b r / > o n T r a c k i n g F a i l u r e C h a n g e d = { t r a c k i n g F a i l u r e R e a s o n . v a l u e = i t } , < b r / > o n V i e w C r e a t e d = { a r S c e n e V i e w R e f . v a l u e = t h i s } , < b r / > o n T o u c h E v e n t = { _ , _ - & g t ; t r u e } , < b r / > o n S e s s i o n U p d a t e d = { s e s s i o n , u p d a t e d F r a m e - & g t ; < b r / > f r a m e . v a l u e = u p d a t e d F r a m e < b r / > a r S e s s i o n . v a l u e = s e s s i o n < b r / > i f ( i s A R S e s s i o n P a u s e d & a m p ; & a m p ; u p d a t e d F r a m e . c a m e r a . t r a c k i n g S t a t e = = T r a c k i n g S t a t e . T R A C K I N G ) i s A R S e s s i o n P a u s e d = f a l s e < b r / > i f ( u p d a t e d F r a m e . c a m e r a . t r a c k i n g S t a t e = = T r a c k i n g S t a t e . T R A C K I N G & a m p ; & a m p ; r e f e r e n c e A n c h o r = = n u l l & a m p ; & a m p ; i s T r a c k i n g S t a b l e ( u p d a t e d F r a m e ) ) c r e a t e S t a b l e A n c h o r ( u p d a t e d F r a m e ) < b r / > i f ( u p d a t e d F r a m e . c a m e r a . t r a c k i n g S t a t e = = T r a c k i n g S t a t e . T R A C K I N G ) { < b r / > e n h a n c e d O v e r l a p L i s t e n e r . u p d a t e R e a l T i m e O v e r l a p ( u p d a t e d F r a m e , c a p t u r e d I m a g e s . s i z e ) < b r / > } e l s e c u r r e n t V i s i b i l i t y O v e r l a p = n u l l < b r / > i f ( ! i s S e s s i o n R e a d y . v a l u e & a m p ; & a m p ; u p d a t e d F r a m e . c a m e r a . t r a c k i n g S t a t e = = T r a c k i n g S t a t e . T R A C K I N G ) i s S e s s i o n R e a d y . v a l u e = t r u e < b r / > i f ( ! i s T a k i n g P h o t o . v a l u e ) u p d a t e C a p t u r e B u t t o n S t a t e ( u p d a t e d F r a m e ) < b r / > d i s t a n c e I n f o = d i s t a n c e D e t e c t o r . u p d a t e ( < b r / > c u r r e n t F r a m e = u p d a t e d F r a m e , < b r / > l a s t C a p t u r e P o s i t i o n = c a p t u r e d I m a g e s . l a s t O r N u l l ( ) ? . p o s i t i o n , < b r / > v i e w p o r t W i d t h = a r S c e n e V i e w R e f . v a l u e ? . w i d t h ? : 0 , < b r / > v i e w p o r t H e i g h t = a r S c e n e V i e w R e f . v a l u e ? . h e i g h t ? : 0 < b r / > ) < b r / > } , < b r / > s e s s i o n C o n f i g u r a t i o n = { s e s s i o n , c o n f i g - & g t ; < b r / > i f ( ! i s S e s s i o n R e a d y . v a l u e | | s h o u l d R e s t o r e S e s s i o n ) { < b r / > c o n f i g . d e p t h M o d e = i f ( s e s s i o n . i s D e p t h M o d e S u p p o r t e d ( C o n f i g . D e p t h M o d e . A U T O M A T I C ) ) C o n f i g . D e p t h M o d e . A U T O M A T I C e l s e C o n f i g . D e p t h M o d e . D I S A B L E D < b r / > c o n f i g . p l a n e F i n d i n g M o d e = C o n f i g . P l a n e F i n d i n g M o d e . H O R I Z O N T A L _ A N D _ V E R T I C A L < b r / > c o n f i g . i n s t a n t P l a c e m e n t M o d e = C o n f i g . I n s t a n t P l a c e m e n t M o d e . L O C A L _ Y _ U P < b r / > c o n f i g . f o c u s M o d e = C o n f i g . F o c u s M o d e . A U T O < b r / > c o n f i g . u p d a t e M o d e = C o n f i g . U p d a t e M o d e . L A T E S T _ C A M E R A _ I M A G E < b r / > c o n f i g . l i g h t E s t i m a t i o n M o d e = C o n f i g . L i g h t E s t i m a t i o n M o d e . D I S A B L E D < b r / > s h o u l d R e s t o r e S e s s i o n = f a l s e < b r / > } < b r / > } < b r / > ) < b r / > < b r / > < b r / > < b r / > / / C a p t u r e B u t t o n < b r / > v a l h a s A n y G a p = c u r r e n t V i e w p o r t G a p s ? . l e t { g a p s - & g t ; g a p s . t o p G a p | | g a p s . l e f t G a p | | g a p s . b o t t o m G a p | | g a p s . r i g h t G a p } ? : f a l s e < b r / > v a l c u r r e n t F r a m e = f r a m e . v a l u e < b r / > v a l s e s s i o n = a r S e s s i o n . v a l u e < b r / > v a l a r S c e n e V i e w = a r S c e n e V i e w R e f . v a l u e < b r / > i f ( c u r r e n t F r a m e = = n u l l | | s e s s i o n = = n u l l | | ! i s S e s s i o n R e a d y . v a l u e | | i s T a k i n g P h o t o . v a l u e | | a r S c e n e V i e w = = n u l l ) r e t u r n < b r / > i f ( c u r r e n t F r a m e . c a m e r a . t r a c k i n g S t a t e ! = T r a c k i n g S t a t e . T R A C K I N G ) r e t u r n < b r / > i f ( ! i s T r a c k i n g S t a b l e ( c u r r e n t F r a m e ) ) r e t u r n < b r / > i f ( i s A R S e s s i o n P a u s e d ) r e t u r n < b r / > i s T a k i n g P h o t o . v a l u e = t r u e < b r / > c a p t u r e d O v e r l a p P e r c e n t a g e = c u r r e n t V i s i b i l i t y O v e r l a p ? . o v e r l a p P e r c e n t a g e < b r / > t r y { < b r / > v a l c a m e r a P o s e = c u r r e n t F r a m e . c a m e r a . p o s e < b r / > v a l i n trinsics=currentFrame.camera.textureIntrinsics
val focalLength=intrinsics.focalLength
val imageDimensions=intrinsics.imageDimensions
val verticalFov=2*atan2(imageDimensions[1].toFloat(),2*focalLength[1])
val horizontalFov=2*atan2(imageDimensions[0].toFloat(),2*focalLength[0])
val distance=0.5f
val forward=floatArrayOf(0f,0f,-distance)
val anchorPose=cameraPose.compose(Pose.makeTranslation(forward))
val anchor=referenceAnchor?:session.createAnchor(anchorPose)
val fixedPose=Pose.makeTranslation(anchorPose.tx(),anchorPose.ty(),anchorPose.tz()).compose(Pose.makeRotation(anchorPose.qx(),anchorPose.qy(),anchorPose.qz(),anchorPose.qw()))
anchorStabilizationMap[anchor]=fixedPose
Handler(Looper.getMainLooper()).postDelayed({
val stabilizedPose=anchorStabilizationMap[anchor]?:anchor.pose
val isFirstImage=referenceAnchor==null||capturedImageCoordinates.isEmpty()
if(isFirstImage){
referenceAnchor=anchor
if(isLandscapeUIMode.value){
val refPose=stabilizedPose
referenceForwardDirection=floatArrayOf(
-2f*(refPose.qx()*refPose.qz()-refPose.qw()*refPose.qy()),
0f,
-(1f-2f*(refPose.qx()*refPose.qx()+refPose.qy()*refPose.qy()))
)
val len=sqrt(referenceForwardDirection[0]*referenceForwardDirection[0]+referenceForwardDirection[2]*referenceForwardDirection[2])
referenceForwardDirection[0]/=len
referenceForwardDirection[2]/=len
}
}else{
if(referenceAnchor==null)referenceAnchor=anchor
}
val baseHeight=2*distance*tan(verticalFov/2)
val baseWidth=2*distance*tan(horizontalFov/2)
val(frameWidth,frameHeight)=baseWidth to baseHeight
val edgeThickness=0.01f
val frameDepth=0.01f
val shouldShowFrameMarker=!isRetakeFlag&&!isResumeFlag&&(configManager.isImageOverlayEnabled()||configManager.isRetakeOverlayEnabled())
if(shouldShowFrameMarker){
val frameColor=Utils.createColorWithTransparency(configManager.getImageOverlayColor(),configManager.getImageOverlayTransparency())
fun createUniqueMaterial():MaterialInstance{
return materialLoader.createColorInstance(color=frameColor,metallic=0.0f,roughness=1.0f,reflectance=0.0f)
}
val anchorNode=AnchorNode(engine=engine,anchor=anchor)
anchorNode.worldPosition=Position(stabilizedPose.tx(),stabilizedPose.ty(),stabilizedPose.tz())
anchorNode.isEditable=false
anchorNode.isVisible=true
val topEdge=CubeNode(engine=engine,size=Size(frameWidth,edgeThickness,frameDepth),materialInstance=createUniqueMaterial())
topEdge.position=Position(0f,frameHeight/2,0f)
topEdge.isVisible=true
anchorNode.addChildNode(topEdge)
val bottomEdge=CubeNode(engine=engine,size=Size(frameWidth,edgeThickness,frameDepth),materialInstance=createUniqueMaterial())
bottomEdge.position=Position(0f,-frameHeight/2,0f)
bottomEdge.isVisible=true
anchorNode.addChildNode(bottomEdge)
val leftEdge=CubeNode(engine=engine,size=Size(edgeThickness,frameHeight,frameDepth),materialInstance=createUniqueMaterial())
leftEdge.position=Position(-frameWidth/2,0f,0f)
leftEdge.isVisible=true
anchorNode.addChildNode(leftEdge)
val rightEdge=CubeNode(engine=engine,size=Size(edgeThickness,frameHeight,frameDepth),materialInstance=createUniqueMaterial())
rightEdge.position=Position(frameWidth/2,0f,0f)
rightEdge.isVisible=true
anchorNode.addChildNode(rightEdge)
val overlayPlane=CubeNode(engine=engine,size=Size(frameWidth,frameHeight,0.001f),materialInstance=createUniqueMaterial())
overlayPlane.position=Position(0f,0f,0f)
overlayPlane.isVisible=true
anchorNode.addChildNode(overlayPlane)
val cameraPosition=floatArrayOf(cameraPose.tx(),cameraPose.ty(),cameraPose.tz())
childNodes+=anchorNode
photoMarkers.value=photoMarkers.value+listOf(cameraPosition)
enhancedOverlapListener.addFrameMarker(pose=stabilizedPose,frameWidth=frameWidth,frameHeight=frameHeight,captureIndex=capturedImages.size,anchor=anchor)
}
},100)
}finally{
Handler(Looper.getMainLooper()).postDelayed({
isTakingPhoto.value=false
isRetaking.value=false
},250)
}


Подробнее здесь: https://stackoverflow.com/questions/798 ... lin-arcore
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»