0

0

ARCore姿态变换:获取相对于自定义原点的姿态

碧海醫心

碧海醫心

发布时间:2025-10-13 10:40:24

|

890人浏览过

|

来源于php中文网

原创

ARCore姿态变换:获取相对于自定义原点的姿态

本文详细介绍了在arcore应用中,如何将一个姿态(pose)从默认的相机坐标系转换为相对于用户自定义的某个原点姿态。通过使用`neutralpose.inverse().compose(centerpose)`这一关键变换公式,开发者可以准确计算出目标姿态相对于特定基准点的相对位置和方向,从而实现更灵活的虚拟内容定位。

在ARCore开发中,我们经常需要获取空间中某个对象的姿态(Pose),例如人脸的中心姿态或某个检测到的平面姿态。这些姿态默认情况下都是相对于设备的相机坐标系而言的,即它们描述了对象在相机视野中的位置和方向。然而,在许多高级应用场景中,我们可能需要将这些姿态转换为相对于一个自定义的“原点姿态”来表示,例如,相对于用户在特定时刻确定的一个初始位置,或者相对于场景中某个固定的虚拟锚点。这种相对姿态的计算对于实现更复杂的交互和虚拟内容定位至关重要。

理解ARCore中的姿态(Pose)

ARCore的Pose对象封装了一个3D位置(平移向量)和一个方向(四元数),它定义了一个局部坐标系相对于其父坐标系(通常是世界坐标系或相机坐标系)的位置和方向。Pose类提供了几个关键方法用于姿态之间的变换:

  • compose(Pose other): 将当前姿态与other姿态组合。如果当前姿态是A,other姿态是B,那么A.compose(B)的结果是,首先应用A的变换,然后在其结果的基础上应用B的变换。这相当于将B的局部坐标系放置到A所定义的坐标系中。
  • inverse(): 返回当前姿态的逆变换。如果当前姿态将一个点从父坐标系转换到子坐标系,那么其逆姿态将点从子坐标系转换回父坐标系。

错误的尝试与分析

初学者在尝试计算相对姿态时,可能会直观地尝试使用以下方式:

Pose centerPose = face.getCenterPose(); // 目标姿态,相对于相机
// 假设 neutralPose 已经设置为自定义的原点姿态
if (neutralPose == null) {
  neutralPose = centerPose; // 首次设置原点姿态
}
// 尝试将 centerPose 变换到 neutralPose 的局部坐标系
centerPose = centerPose.compose(neutralPose.inverse());

这种方法的问题在于,centerPose.compose(neutralPose.inverse())的语义是:先将centerPose的变换应用到原点,然后在这个新位置上应用neutralPose.inverse()的变换。这实际上会将centerPose向远离neutralPose原点的方向移动,而不是将其“带入”neutralPose的局部坐标系。结果会导致当头部旋转时,虚拟对象出现剧烈的平移,无法保持相对稳定。

正确的相对姿态计算方法

要正确计算centerPose相对于neutralPose的相对姿态,我们需要将centerPose从世界坐标系(或相机坐标系)转换到以neutralPose为原点的局部坐标系中。这可以通过以下变换顺序实现:

魔珐星云
魔珐星云

无需昂贵GPU,一键解锁超写实/二次元等多风格3D数字人,跨端适配千万级并发的具身智能平台。

下载
Pose relativePose = neutralPose.inverse().compose(centerPose);

原理分析:

  1. neutralPose.inverse(): 这一步创建了一个新的变换,它将世界坐标系中的任何点或姿态,转换到以neutralPose为原点的局部坐标系中。可以理解为,它“重新定义”了世界的原点,使其与neutralPose重合。
  2. .compose(centerPose): 在完成了第一步的坐标系转换后,我们再将centerPose应用到这个新的、以neutralPose为原点的坐标系中。这样,centerPose的位置和方向就相对于neutralPose的局部坐标系来表达了。

简而言之,我们首先将整个世界(包括centerPose)“移动和旋转”,使得neutralPose成为新的世界原点,然后在这个新的世界中观察centerPose的位置。

示例代码

以下代码片段展示了如何在ARCore应用中实现这一逻辑:

import com.google.ar.core.Pose;
import com.google.ar.core.AugmentedFace;
import android.util.Log;

public class ArCoreRelativePoseCalculator {

    private Pose neutralPose = null; // 用于存储基准原点姿态

    /**
     * 设置或更新基准原点姿态。通常在应用启动、用户交互或特定事件时调用。
     * @param initialPose 初始的基准姿态,例如首次检测到的人脸姿态。
     */
    public void setNeutralPose(Pose initialPose) {
        if (neutralPose == null) {
            neutralPose = initialPose;
            Log.d("ARCoreTutorial", "Neutral Pose set: " + neutralPose.toString());
        }
    }

    /**
     * 计算当前目标姿态相对于已设置的基准原点姿态的相对姿态。
     * @param currentTargetPose 当前需要计算相对姿态的目标姿态(例如,当前帧的人脸姿态)。
     * @return 如果 neutralPose 已设置,返回 relativePose;否则返回 null。
     */
    public Pose calculateRelativePose(Pose currentTargetPose) {
        if (neutralPose == null) {
            Log.w("ARCoreTutorial", "Neutral Pose not set. Cannot calculate relative pose.");
            return null;
        }

        // 核心计算:neutralPose 的逆变换,然后与 currentTargetPose 组合
        Pose relativePose = neutralPose.inverse().compose(currentTargetPose);

        Log.d("ARCoreTutorial", "Current Target Pose: " + currentTargetPose.toString());
        Log.d("ARCoreTutorial", "Relative Pose to Neutral: " + relativePose.toString());

        return relativePose;
    }

    // 示例用法(在ARCore的onUpdate或渲染循环中)
    public void onUpdate(AugmentedFace face) {
        if (face == null) {
            return;
        }

        Pose centerPose = face.getCenterPose();

        // 首次检测到人脸时,将其作为基准原点姿态
        if (neutralPose == null) {
            setNeutralPose(centerPose);
            // 此时相对姿态是单位姿态,因为 centerPose 相对于自身
            // 可以选择在这里不进行后续计算,或者返回一个单位姿态
            return;
        }

        // 计算当前人脸姿态相对于初始人脸姿态的相对姿态
        Pose relativeFacePose = calculateRelativePose(centerPose);

        if (relativeFacePose != null) {
            // 现在 relativeFacePose 包含了当前人脸相对于初始人脸的位置和方向信息
            // 可以在此基础上进行后续操作,例如将虚拟物体附加到这个相对姿态,
            // 使其始终相对于用户最初的头部位置保持固定。
            // 例如:渲染一个虚拟帽子,它会随着用户的头部移动和旋转,
            // 但始终保持与用户初始头部姿态的相对位置关系。
            // SomeRenderer.renderObject(relativeFacePose);
        }
    }
}

注意事项与最佳实践

  1. 何时设置neutralPose: neutralPose的设置时机非常关键。它应该在用户期望建立“原点”的时刻进行,例如:
    • 应用启动时,将相机当前姿态作为原点。
    • 用户第一次点击屏幕时,将点击位置的姿态作为原点。
    • 检测到特定AR对象时,将该对象的姿态作为原点。
    • 在人脸跟踪中,当用户头部第一次处于“中立”位置时。
  2. Pose对象的不可变性: ARCore的Pose对象是不可变的。compose()和inverse()方法都会返回一个新的Pose对象,而不是修改原始对象。因此,务必将这些方法的返回值赋给一个新的Pose变量。
  3. 应用场景: 相对姿态计算在以下场景中非常有用:
    • 虚拟物体锚定: 将虚拟物体锚定到某个用户自定义的基准点,而不是相机或世界原点。
    • 手势识别: 分析手部相对于身体或另一个手部的姿态变化。
    • 校准: 在需要用户对齐或重置某个特定姿态时。
    • 多用户协作: 将不同用户的AR内容同步到共同的参考系中。
  4. 与Anchor的区别: Pose描述的是瞬时位置和方向,而Anchor则是一个在ARCore跟踪的世界中固定不变的点。虽然Anchor可以用来获取一个稳定的Pose作为neutralPose,但直接使用Pose进行相对计算在许多情况下更为灵活和直接。

总结

通过理解Pose的inverse()和compose()方法的精确语义,并采用neutralPose.inverse().compose(centerPose)这一关键公式,开发者可以有效地在ARCore中计算出相对于自定义原点的姿态。掌握这一技巧,将极大地增强AR应用中虚拟内容定位的灵活性和交互的丰富性,为用户带来更加沉浸和个性化的增强现实体验。

相关专题

更多
Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

4

2026.01.15

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

28

2026.01.15

公务员调剂条件 2026调剂公告时间
公务员调剂条件 2026调剂公告时间

(一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

36

2026.01.15

国考成绩查询入口 国考分数公布时间2026
国考成绩查询入口 国考分数公布时间2026

笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

6

2026.01.15

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

63

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

34

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

73

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

20

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

31

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Excel 教程
Excel 教程

共162课时 | 11.8万人学习

Java 教程
Java 教程

共578课时 | 46.2万人学习

Uniapp从零开始实现新闻资讯应用
Uniapp从零开始实现新闻资讯应用

共64课时 | 6.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号