Android手机中的加速度计与陀螺仪
传感器和加速度传感器的区别与联系陀螺仪原理陀螺仪的原理就是,一个旋转物体的旋转轴所指的方向在不受外力影响时,是不会改变的。人们根据这个道理,用它来保持方向。然后用多种方法读取轴所指 示的方向,并自动将数据信号传给控制系统。我们骑自行车其实也是利用了这个原理。轮子转得越快越不容易倒,因为车轴有一股保持水平的力量。陀螺仪又叫角速度传感器,是不同于加速度(G-sensor)的,他的测量物理...
传感器和加速度传感器的区别与联系
陀螺仪原理
陀螺仪的原理就是,一个旋转物体的旋转轴所指的方向在不受外力影响时,是不会改变的。人们根据这个道理,用它来保持方向。然后用多种方法读取轴所指 示的方向,并自动将数据信号传给控制系统。我们骑自行车其实也是利用了这个原理。轮子转得越快越不容易倒,因为车轴有一股保持水平的力量。
陀螺仪又叫角速度传感器,是不同于加速度(G-sensor)的,他的测量物理量是偏转、倾斜时的转动角速度。在手机上,仅用加速度计没办法测量或重构出完整的3D动作,测不到转动的动作的,G-sensor只能检测轴向的线性动作。但陀螺仪则可以对转动、偏转的动作做很好的测量,这样就可以精确分析判断出使用者的实际动作。 |
陀螺仪,原理:用在手机里面的陀螺仪都是MEMS陀螺仪,里面的微机械结构为振动件,如下图(不同意排名最高的说法,有旋转件的是传统的陀螺仪),通过测量旋转产生的科氏加速度来获得角速度。用途:照相防抖,以及配合加速度计(有的还有磁传感器)形成的组合传感器来完成特定的功能(如惯性导航,还有玩游戏时的一些角速度测试)
加速度计原理
加速度传感器是一种能够测量加速力的电子设备。加速力就是当物体在加速过程中作用在物体上的力,就好比地球引力,也就是重力。加速力可以是个常量,比如g,也可以是变量。加速度计有两种:一种是角加速度计,是由陀螺仪(角速度传感器)的改进的。另一种就是线加速度计。
线加速度计的原理是惯性原理,也就是力的平衡,A(加速度)=F(惯性力)/M(质量) 我们只需要测量F就可以了。怎么测量F?用电磁力去平衡这个力就可以了。就可以得到 F对应于电流的关系。只需要用实验去标定这个比例系数就行了。当然中间的信号传输、放大、滤波就是电路的事了。
多数加速度传感器是根据压电效应的原理来工作的。
通过测量由于重力引起的加速度,你可以计算出设备相对于水平面的倾斜角度。
加速度计,原理:用在手机里的加速度计同样是MEMS的,也是由振动结构,由于外界加速度会影响结构的振动特性,由此来测量加速度。
什么是线性加速度计?由于加速度计的输出包含了重力加速度,线性加速度计简单来说就是排除了重力加速度的影响得到的值。
线性加速度传感器是加速度传感器减去重力影响获取的数据。
单位是m/s^2,坐标系统与加速度传感器相同。
加速度传感器、重力传感器和线性加速度传感器的计算公式如下:
加速度 = 重力 + 线性加速度(acceleration = gravity + linear_acceleration )
陀螺仪传感器和加速度传感器的区别:
陀螺仪测角速度的,加速度是测线性加速度的。前者是惯性原理,后者是利用的力平衡原理。
加速度计在较长时间的测量值是正确的,而在较短时间内由于信号噪声的存在,而有误差。陀螺仪在较短时间内则比较准确而较长时间则会有与漂移而存有误差。因此,需要两者(相互调整)来确保航向的正确。
区别:从原理来说,陀螺仪和加速度计都是通过振动测量加速度的,只不过陀螺仪测量的是科氏加速度,而加速度计是测量的直接加速度。MEMS陀螺仪可以简单理解为一个谐振器+加速度计。因此陀螺仪的结构要比加速度计复杂得多,技术也难得多。
当前Android设备中已经集成进数十个传感器,我们比较常见的有加速度传感器、陀螺仪、地磁传感器等。
虽然种类繁多,但在Framework中仅仅提供了几个类和接口就把传感器相关的功能搞定了。下面我们以加速度传感器为例,引领大家走入Android传感器的世界。
传感器世界的坐标系
x轴:从左到右
y轴:从下到上
z轴:从内到外
这个坐标系与Android 2D API中的不同,传感器中的返回值都以此坐标系为准。
API概况
sensor相关API被放到了android.hardware包下,我们主要使用的类有三个:Sensor、SensorEvent、SensorManager以及一个SensorEventListener接口。
SensorManager顺其自然的担任起管理的工作,负责注册监听某Sensor的状态;Sensor的数据通过SensorEvent返回。
获得设备中所有可用sensor
SensorManager提供getSensorList方法,传入TYPE_ALL,即可得到当前设备所有传感器。
SensorManager sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
//mTvInfo.setText("sensors: " + sensors.size());
Log.d(TAG, "sensors: " + sensors.size());
for (int i = 0;i < sensors.size();++i) {
Log.d(TAG,"sensor name: "+sensors.get(i).getName());
Log.d(TAG,"sensor vendor: "+sensors.get(i).getVendor());
Log.d(TAG,"sensor power: "+sensors.get(i).getPower());
Log.d(TAG, "sensor resolution: " + sensors.get(i).getResolution());
}
Sensor编码套路
public class SensorActivity extends Activity, implements SensorEventListener {
private final SensorManager mSensorManager;
private final Sensor mAccelerometer;
public SensorActivity() {
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
}
}
不同的传感器被提取共性后,由上面的编码套路规定起来,一切就变得如此简单啦。
加速度传感器的背景
这里的加速度特指重力加速度,所以在静止时重力传感器的返回值与加速度传感器值相同。
地表上静止物体的重力加速度约为9.8 m/s^2.
借用SensorManager中的常量:
public static final float STANDARD_GRAVITY = 9.80665F;
我们可以借助三轴上的值来确定设备的状态(请参考上面的坐标图),比如:
1、当x轴的值接近重力加速度时,说明设备的左边朝下。
2、当x轴的值接近负的g值时,说明设备的右边朝下。
3、当y轴的值接近g值时,说明设备的下边超下(与上图一样)。
4、当y轴的值接近负的g值时,说明设备的上边朝下(倒置)。
5、当z轴的值接近g值时,说明设备的屏幕朝上。
6、当z轴的值接近负的g值时,说明设备屏幕朝下。
具体代码如下:
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
Log.d("linc", "value size: " + sensorEvent.values.length);
float xValue = sensorEvent.values[0];// Acceleration minus Gx on the x-axis
float yValue = sensorEvent.values[1];//Acceleration minus Gy on the y-axis
float zValue = sensorEvent.values[2];//Acceleration minus Gz on the z-axis
mTvInfo.setText("x轴: "+xValue+" y轴: "+yValue+" z轴: "+zValue);
if(xValue > mGravity) {
mTvInfo.append("\n重力指向设备左边");
} else if(xValue < -mGravity) {
mTvInfo.append("\n重力指向设备右边");
} else if(yValue > mGravity) {
mTvInfo.append("\n重力指向设备下边");
} else if(yValue < -mGravity) {
mTvInfo.append("\n重力指向设备上边");
} else if(zValue > mGravity) {
mTvInfo.append("\n屏幕朝上");
} else if(zValue < -mGravity) {
mTvInfo.append("\n屏幕朝下");
}
}
文章内容部分参考于:https://blog.csdn.net/lincyang/article
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)