ARCore:如何获取Pose相对于另一Pose的位置与姿态
问题根源
你代码里的Pose变换顺序完全搞反了,而且直接用相机坐标系下的Pose做基准是错误的——相机Pose每帧都在变,以此为基准必然会导致头部旋转时出现位置偏移。ARCore的Pose.compose()是右乘逻辑,你的写法相当于把变换方向搞反了,根本得不到正确的相对姿态。
正确实现方式
方式一:基于世界坐标系的Pose转换
先把面部相对于相机的Pose转成世界坐标系下的Pose,再以初始状态的世界Pose为基准计算相对变换:
// 全局变量 Pose neutralWorldPose = null; Session arSession; // 你的ARCore Session实例 // 每帧处理面部Pose时的代码 Pose faceCameraPose = face.getCenterPose(); // 将相机坐标系下的面部Pose转换为世界坐标系Pose Pose faceWorldPose = arSession.getCamera().getDisplayOrientedPose().compose(faceCameraPose); // 首次检测到面部时,记录此时的世界Pose作为原点基准 if (neutralWorldPose == null) { neutralWorldPose = faceWorldPose; } // 计算当前面部相对于原点基准的Pose Pose relativePose = neutralWorldPose.inverse().compose(faceWorldPose);
- 核心逻辑:
getDisplayOrientedPose()拿到相机在世界坐标系中的姿态- 通过相机世界姿态叠加面部相对相机的姿态,得到面部的世界姿态
- 用基准姿态的逆姿态左乘当前世界姿态,就能得到当前姿态相对于基准的正确变换(ARCore中
A.inverse().compose(B)就是求B相对于A的Pose)
方式二:用Anchor固定原点(更稳定)
如果需要长时间跟踪,建议用Anchor绑定初始面部的世界位置,ARCore会自动维护这个锚点的稳定性,抵消相机漂移的影响:
// 全局变量 Anchor neutralAnchor = null; Session arSession; // 每帧处理代码 Pose faceCameraPose = face.getCenterPose(); Pose faceWorldPose = arSession.getCamera().getDisplayOrientedPose().compose(faceCameraPose); // 首次检测时创建锚点 if (neutralAnchor == null) { neutralAnchor = arSession.createAnchor(faceWorldPose); } // 获取锚点的当前世界姿态,计算相对变换 Pose anchorWorldPose = neutralAnchor.getPose(); Pose relativePose = anchorWorldPose.inverse().compose(faceWorldPose);
重要提醒
- 绝对不要用相机坐标系下的Pose作为基准,相机的移动会让基准不断偏移,必然出现位置跳变。
- ARCore Pose的变换顺序不能乱:
A.compose(B)是先执行B的变换,再执行A的变换;求相对姿态必须用基准.inverse().compose(目标)的格式。
内容的提问来源于stack exchange,提问作者John Goering
相关产品推荐
相关产品推荐

