XR开发中的坐标系

XR开发中的坐标系

最近的诸多问题都出在了坐标系上,收集了一下零散在各个地方的资料,汇总一下各个场合下的坐标系,强行做个笔记。

基础知识

首先我们在谈论坐标系的时候,一般是会讲到左手坐标系和右手坐标系,它们是怎么定义的呢?

左手坐标系

我们可以拿出我们的左手。

  • 大拇指代表X轴,大拇指指向的方向,代表了X轴正方向
  • 食指代表Y轴,食指指向方向,代表了Y轴正方向
  • 中指代表Z轴,中指指向方向,代表了Z轴正方向

2022-08-31_16-20-17

请牢记这个标准姿势,后面所有的左手坐标系都是在这个姿势的情况下做旋转

右手坐标系

拿出我们的右手,同样的:

  • 大拇指代表X轴,大拇指指向的方向,代表了X轴正方向
  • 食指代表Y轴,食指指向方向,代表了Y轴正方向
  • 中指代表Z轴,中指指向方向,代表了Z轴正方向

2022-08-31_16-58-11

pitch,yaw,roll的旋转正方向

除此之外,还会有一个旋转的问题,因为在6dof的世界中,我们除了position之外还会有一个orientation的旋转问题,在真实世界中我们一般会用pitchyawroll来分别表征物体沿着X轴Y轴Z轴的运动。

2022-08-31_17-10-43

  • 这个示意图中使用的是右手坐标系,所以整个旋转的正方向,就要使用右手来做
  • 同样的,如果是左手坐标系,那么整个旋转的正方向就要用左手来做了,这边就略过了。

工程中的坐标系

HMD

整个通路上,会有这么几个坐标系:

  • IMU坐标系
  • Sensor Stack坐标系(Android端)
  • qvrservice坐标系
  • config配置文件中的坐标系
    • 这个部分的知识是可以通过阅读qcom spec来获得的
  • openxr的坐标系
  • unity的坐标系。

IMU坐标系

IMU的坐标系其实是固定的,或者可以咨询厂家是否会变动,一般来说是右手系,然后要看贴片的方向和具体位置,再来做一下手的旋转,才可以确定好各个方向。如下图所示,这个是IMU本身的坐标系。

2022-08-31_18-12-07

安装后的坐标系,因为牵扯到贴片,所以就会有一个旋转(用右手开始转就行):

2022-08-31_18-15-47

qvrservice坐标系(SLAM坐标系)

根据高通的文档,qvrservice的坐标系是X轴向上Y轴向左Z轴向自己的,是右手坐标系。

坐标系示意图:

2022-08-31_18-31-24

OpenXR坐标系

在OpenXR中,坐标系是有着准确定义的:

https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#reference-spaces

2022-08-31_20-33-56

OpenXR的坐标系是X轴向右Y轴向上Z轴向自己的,是右手坐标系。

2022-08-31_20-43-40

Unity坐标系(应用坐标系)

Unity的坐标系是左手系:https://docs.unity3d.com/560/Documentation/Manual/Transforms.html

直接就盗图了:

2022-08-31_20-54-32

HMD的坐标系次序图

这样我们把整个流程串一下,就可以得到下面这个图:

2022-08-31_21-01-19

手柄Controller

手柄的通路其实和头显大同小异:

  • IMU坐标系
  • Vendor(方案供应商)坐标系
  • ControllerService坐标系
  • OpenXR坐标系
  • 手柄坐标系
  • Unity坐标系(应用坐标系)

IMU坐标系

手柄上的IMU的坐标系,根据实际项目拿到的图例如下:

image-20221028170123117

Vendor坐标系

Vendor坐标系实际是一个黑盒的东西,从算法供应商那边得到的答复是“我们会把手柄的pose转化到qvrservice(slam)坐标系”。

2022-08-31_18-31-24

ControllerService坐标系

OpenXR坐标系

这边就直接笼为一谈了,因为目前架构下ControllerService的数据会做一个预测算法后给到OpenXR Runtime,两者的坐标系是一致的:

2022-08-31_20-43-40

手柄坐标系

在OpenXR中,手柄本身也是有一个坐标系的概念的,这个是区别于头显HMD的。

https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#semantic-path-standard-pose-identifiers

2022-09-01_11-33-43

在OpenXR的Controller中,会有两个关键的坐标系:gripaim

其中的X,Y,Z三轴,在spec中也是有着严格定义的,实际上就是我们图中定义的:

  • grip

      • The grip orientation’s +X axis: When you completely open your hand to form a flat 5-finger pose, the ray that is normal to the user’s palm (away from the palm in the left hand, into the palm in the right hand).
      • The grip orientation’s -Z axis: When you close your hand partially (as if holding the controller), the ray that goes through the center of the tube formed by your non-thumb fingers, in the direction of little finger to thumb.
      • The grip orientation’s +Y axis: orthogonal to +Z and +X using the right-hand rule.
  • aim

      • For tracked hands: The ray that follows platform conventions for how the user aims at objects in the world with their entire hand, with +Y up, +X to the right, and -Z forward. The ray chosen will be runtime-dependent, for example, a ray emerging from the palm parallel to the forearm.
      • For handheld motion controllers: The ray that follows platform conventions for how the user targets objects in the world with the motion controller, with +Y up, +X to the right, and -Z forward. This is usually for applications that are rendering a model matching the physical controller, as an application rendering a virtual object in the user’s hand likely prefers to point based on the geometry of that virtual object. The ray chosen will be runtime-dependent, although this will often emerge from the frontmost tip of a motion controller.

简单来说,aim和pose都是右手系:

  • grip
    • 左手手柄:X轴正方向远离手掌Z轴负方向是握紧后小拇指往大拇指的连线方向Y轴由右手系X轴和Z轴的方向决定
    • 右手手柄:X轴正方向指向手掌Z轴负方向是握紧后小拇指往大拇指的连线方向Y轴由右手系X轴和Z轴的方向决定
  • aim:X轴向右Y轴向上Z轴向自己

这么说虽然有点抽象,但是要记住,grip和aim实际是要从imu的pose做一些旋转得到的(因为imu实际摆放和安装的位置跟aim还有grip可能有出入)。

2022-09-01_11-49-29

  • 我们产品上手柄IMU的位置跟aim pose是相同的,所以就可以认为imu的数据就是aim orientation
  • 但是aimgrip存在一个夹角,需要做一个旋转矩阵。

我们以实际的pico左手柄图来做一个举例:

2022-09-01_14-15-47

在Monado Runtime的实现中,psmv的controller也是按照这个思路去做的:

2022-09-01_14-35-58

手柄的坐标系次序图

同样的,我们最后用一个次序图来总结一下整个通路:

image-20221028170244915

实际上可以看出,手柄的pose和aim是一种local的坐标系,而当把手柄放到openxr中时,就会遵循openxr的世界坐标系,最后再到应用端,就跟头显一样了。

最后

只要确定好的左手系和右手系,剩下的就是给定两个轴的正方向,然后比划出坐标系。在这个期间的坐标系大部分都是可以通过旋转来确认的,比如从qvrservice变换到openxr坐标系,就需要沿着Z轴做旋转,旋转角度为-90°,即roll=-90,如下图所示:

2022-09-01_15-05-48

其他的坐标系变换也是相同的道理,当厘清了这个转换关系,那么在对齐问题的过程中就可以做到心中有数了。