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设备坐标系和陀螺仪正方向规则画在了一起。你可以对照着看,一目了然。
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轴的方向和右手定则,陀螺仪的世界就清晰了。
我个人习惯在项目初期,先写一个简单的测试页面,把三个轴的实时数据打印出来,然后手动转动手机,验证坐标系是否正确。这一步花不了几分钟,但能避免后面几小时的排查时间。
好,这节课就到这里。记住:坐标系是基础,基础不牢,地动山摇。