8、坐标系与方向:Android 设备坐标系,陀螺仪的正方向规则

好,咱们今天聊点硬核的。坐标系这个东西,说白了就是给手机定个“东南西北”。你想想看,陀螺仪测的是旋转,但旋转总得有个参考系吧?没有坐标系,你测出来的数据就是一堆没意义的数字。

我记得刚接触Android传感器那会儿,踩过一个坑:明明手机平放着,陀螺仪的Z轴数据却一直在飘。后来才发现,是我对坐标系的理解出了问题。嗯,这节课咱们就把这事彻底捋清楚。

8.1 Android 设备坐标系长什么样?

Android官方定义了一套标准坐标系。这套坐标系是固定在手机上的,也就是说,不管你怎么转手机,坐标轴都跟着手机一起转。这叫“设备坐标系”(Device Coordinate System)。

具体规则如下:

  • X轴:水平向右。手机屏幕短边方向,从左边指向右边。
  • Y轴:垂直向上。手机屏幕长边方向,从底部指向顶部。
  • Z轴:垂直于屏幕向外。从手机背面指向正面(也就是指向你)。

这里有个容易混淆的点:Z轴的正方向是朝屏幕外的。我见过不少新手以为Z轴是穿进屏幕的,结果算出来的方向全是反的。你想想看,如果Z轴朝里,那手机平放时重力加速度就是正的,但实际测量值是负的——这不就乱套了吗?

核心记忆法:把手机想象成一块平板,X轴向右,Y轴向上,Z轴指向你。就这么简单。

8.2 陀螺仪的正方向规则

陀螺仪测量的是角速度,单位是弧度/秒(rad/s)。正方向怎么定?用的是右手定则

右手定则:

  • 伸出右手,大拇指指向坐标轴的正方向。
  • 四指弯曲的方向,就是绕该轴旋转的正方向

具体到每个轴:

旋转轴 正方向(右手定则) 实际场景
绕X轴 手机顶部朝你翻转(仰头) 手机平放,抬起顶部
绕Y轴 手机右侧朝你翻转(右倾) 手机平放,抬起右侧
绕Z轴 手机逆时针旋转(从屏幕上方看) 手机平放,向左旋转

我的小技巧:如果你记不住右手定则,就记住“正方向是让数值变大的方向”。比如手机平放时,绕X轴正转(顶部抬起),陀螺仪的X轴数据就是正的。反过来,顶部压下,数据就是负的。

8.3 坐标系与传感器数据的对应关系

在实际开发中,你拿到的陀螺仪数据是一个三维向量:[x, y, z]。这三个值分别对应绕X、Y、Z轴的角速度。

举个例子:

  • 手机平放在桌上,静止不动 → [0, 0, 0]
  • 手机绕X轴顺时针旋转(顶部压下) → X值为
  • 手机绕Y轴逆时针旋转(右侧抬起) → Y值为
  • 手机绕Z轴顺时针旋转(从屏幕上方看) → Z值为

我曾经在做一个AR导航项目时,发现手机指向的方向总是偏了90度。排查了半天,原来是坐标系搞混了——我把设备坐标系和世界坐标系混为一谈了。说白了,陀螺仪给的是“手机自己怎么转”,不是“手机相对于地球怎么转”。这两个概念千万别搞混。

8.4 坐标系可视化:一张图看懂

下面这张SVG图,把Android设备坐标系和陀螺仪正方向规则画在了一起。你可以对照着看,一目了然。

Android 设备坐标系与陀螺仪正方向 手机屏幕(俯视图) +X +Y +Z (朝外) 绕X轴正转 (顶部抬起) 绕Y轴正转 (右侧抬起) 绕Z轴正转 (逆时针) 右手定则:大拇指指向轴正方向,四指弯曲方向即为旋转正方向

8.5 避坑指南:坐标系相关的常见错误

做项目这么多年,坐标系相关的坑我踩过不少。下面这几个是高频雷区,你一定要注意:

坑1:手机横竖屏切换时坐标系不变

我曾经以为手机横过来之后,X轴和Y轴会互换。其实不会!Android设备坐标系是固定在手机硬件上的。横屏时,屏幕显示方向变了,但传感器坐标系纹丝不动。如果你需要根据屏幕方向调整数据,得自己用getRotation()做映射。

坑2:Z轴正方向搞反

这个太常见了。记住:Z轴正方向是指向屏幕外。如果你把手机屏幕朝上平放,Z轴指向天花板。如果你把手机屏幕朝下扣在桌上,Z轴指向地板。陀螺仪绕Z轴旋转时,从屏幕上方看,逆时针为正。

坑3:把设备坐标系当成世界坐标系

陀螺仪告诉你的是“手机自己转了多少”,不是“手机相对于地球转了多少”。如果你想知道手机相对于地面的方向,需要结合加速度计和地磁传感器做融合。这个后面章节会讲,但你现在就要有这个意识。

8.6 代码验证:打印当前坐标系下的陀螺仪数据

光说不练假把式。咱们写一小段代码,看看实际数据长什么样:

// 获取陀螺仪传感器
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor gyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

// 注册监听器
SensorEventListener listener = new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
        float x = event.values[0]; // 绕X轴角速度
        float y = event.values[1]; // 绕Y轴角速度
        float z = event.values[2]; // 绕Z轴角速度
        
        // 打印数据
        Log.d("Gyro", String.format("X: %.2f, Y: %.2f, Z: %.2f", x, y, z));
        
        // 判断方向
        if (x > 0.5f) {
            Log.d("Gyro", "手机顶部正在抬起");
        } else if (x < -0.5f) {
            Log.d("Gyro", "手机顶部正在压下");
        }
    }
    
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // 精度变化时处理
    }
};

sensorManager.registerListener(listener, gyroscope, SensorManager.SENSOR_DELAY_NORMAL);

这段代码很简单。你把它跑起来,然后手动转动手机,看看Logcat里的数据变化。我建议你拿个手机实际试一下,感受一下“正方向”到底是什么意思。嗯,动手永远比光看强。

8.7 小结:坐标系是陀螺仪的灵魂

说白了,坐标系就是陀螺仪的“语言”。你听不懂这门语言,数据就是一堆乱码。但一旦你掌握了X、Y、Z轴的方向和右手定则,陀螺仪的世界就清晰了。

我个人习惯在项目初期,先写一个简单的测试页面,把三个轴的实时数据打印出来,然后手动转动手机,验证坐标系是否正确。这一步花不了几分钟,但能避免后面几小时的排查时间。

好,这节课就到这里。记住:坐标系是基础,基础不牢,地动山摇。


公众号:蓝海资料掘金营,微信 deep3321