• [转]Android重力感应开发


    http://blog.csdn.net/mad1989/article/details/20848181

    一、手机中常用的传感器

    在Android2.3 gingerbread系统中,google提供了11种传感器供应用层使用,具体如下:(Sensor类)

    #define SENSOR_TYPE_ACCELEROMETER 1 //加速度
    #define SENSOR_TYPE_MAGNETIC_FIELD 2 //磁力
    #define SENSOR_TYPE_ORIENTATION 3 //方向
    #define SENSOR_TYPE_GYROSCOPE 4 //陀螺仪
    #define SENSOR_TYPE_LIGHT 5 //光线感应
    #define SENSOR_TYPE_PRESSURE 6 //压力
    #define SENSOR_TYPE_TEMPERATURE 7 //温度
    #define SENSOR_TYPE_PROXIMITY 8 //接近
    #define SENSOR_TYPE_GRAVITY 9 //重力
    #define SENSOR_TYPE_LINEAR_ACCELERATION 10//线性加速度
    #define SENSOR_TYPE_ROTATION_VECTOR 11//旋转矢量

    1-1加速度传感器

    加速度传感器又叫G-sensor,返回x、y、z三轴的加速度数值。
    该数值包含地心引力的影响,单位是m/s^2。
    将手机平放在桌面上,x轴默认为0,y轴默认0,z轴默认9.81。
    将手机朝下放在桌面上,z轴为-9.81。
    将手机向左倾斜,x轴为正值。
    将手机向右倾斜,x轴为负值。
    将手机向上倾斜,y轴为负值。
    将手机向下倾斜,y轴为正值。
    加速度传感器可能是最为成熟的一种mems产品,市场上的加速度传感器种类很多。
    手机中常用的加速度传感器有BOSCH(博世)的BMA系列,AMK的897X系列,ST的LIS3X系列等。
    这些传感器一般提供±2G至±16G的加速度测量范围,采用I2C或SPI接口和MCU相连,数据精度小于16bit。

    1-2 磁力传感器

    磁力传感器简称为M-sensor,返回x、y、z三轴的环境磁场数据。
    该数值的单位是微特斯拉(micro-Tesla),用uT表示。
    单位也可以是高斯(Gauss),1Tesla=10000Gauss。
    硬件上一般没有独立的磁力传感器,磁力数据由电子罗盘传感器提供(E-compass)。
    电子罗盘传感器同时提供下文的方向传感器数据。

    1-3 方向传感器

    方向传感器简称为O-sensor,返回三轴的角度数据,方向数据的单位是角度。
    为了得到精确的角度数据,E-compass需要获取G-sensor的数据,
    经过计算生产O-sensor数据,否则只能获取水平方向的角度。
    方向传感器提供三个数据,分别为azimuth、pitch和roll。
    azimuth:方位,返回水平时磁北极和Y轴的夹角,范围为0°至360°。
    0°=北,90°=东,180°=南,270°=西。
    pitch:x轴和水平面的夹角,范围为-180°至180°。
    当z轴向y轴转动时,角度为正值。
    roll:y轴和水平面的夹角,由于历史原因,范围为-90°至90°。
    当x轴向z轴移动时,角度为正值。
    电子罗盘在获取正确的数据前需要进行校准,通常可用8字校准法。
    8字校准法要求用户使用需要校准的设备在空中做8字晃动,
    原则上尽量多的让设备法线方向指向空间的所有8个象限。
    手机中使用的电子罗盘芯片有AKM公司的897X系列,ST公司的LSM系列以及雅马哈公司等等。
    由于需要读取G-sensor数据并计算出M-sensor和O-sensor数据,
    因此厂商一般会提供一个后台daemon来完成工作,电子罗盘算法一般是公司私有产权。

    1-4 陀螺仪传感器

    陀螺仪传感器叫做Gyro-sensor,返回x、y、z三轴的角加速度数据。
    角加速度的单位是radians/second。
    根据Nexus S手机实测:
    水平逆时针旋转,Z轴为正。
    水平逆时针旋转,z轴为负。
    向左旋转,y轴为负。
    向右旋转,y轴为正。
    向上旋转,x轴为负。
    向下旋转,x轴为正。
    ST的L3G系列的陀螺仪传感器比较流行,iphone4和google的nexus s中使用该种传感器。

    1-5 光线感应传感器

    光线感应传感器检测实时的光线强度,光强单位是lux,其物理意义是照射到单位面积上的光通量。
    光线感应传感器主要用于Android系统的LCD自动亮度功能。
    可以根据采样到的光强数值实时调整LCD的亮度。

    1-6 压力传感器

    压力传感器返回当前的压强,单位是百帕斯卡hectopascal(hPa)。

    1-7 温度传感器

    温度传感器返回当前的温度。

    1-8 接近传感器

    接近传感器检测物体与手机的距离,单位是厘米。
    一些接近传感器只能返回远和近两个状态,
    因此,接近传感器将最大距离返回远状态,小于最大距离返回近状态。
    接近传感器可用于接听电话时自动关闭LCD屏幕以节省电量。
    一些芯片集成了接近传感器和光线传感器两者功能。
    下面三个传感器是Android2新提出的传感器类型,目前还不太清楚有哪些应用程序使用。

    1-9 重力传感器

    重力传感器简称GV-sensor,输出重力数据。
    在地球上,重力数值为9.8,单位是m/s^2。
    坐标系统与加速度传感器相同。
    当设备复位时,重力传感器的输出与加速度传感器相同。

    1-10 线性加速度传感器

    线性加速度传感器简称LA-sensor。
    线性加速度传感器是加速度传感器减去重力影响获取的数据。
    单位是m/s^2,坐标系统与加速度传感器相同。
    加速度传感器、重力传感器和线性加速度传感器的计算公式如下:
    加速度 = 重力 + 线性加速度

    1-11 旋转矢量传感器

    旋转矢量传感器简称RV-sensor。
    旋转矢量代表设备的方向,是一个将坐标轴和角度混合计算得到的数据。
    RV-sensor输出三个数据:
    x*sin(theta/2)
    y*sin(theta/2)
    z*sin(theta/2)
    sin(theta/2)是RV的数量级。
    RV的方向与轴旋转的方向相同。
    RV的三个数值,与cos(theta/2)组成一个四元组。
    RV的数据没有单位,使用的坐标系与加速度相同。
    举例:
    sensors_event_t.data[0] = x*sin(theta/2)
    sensors_event_t.data[1] = y*sin(theta/2)
    sensors_event_t.data[2] = z*sin(theta/2)
    sensors_event_t.data[3] = cos(theta/2)
    GV、LA和RV的数值没有物理传感器可以直接给出,
    需要G-sensor、O-sensor和Gyro-sensor经过算法计算后得出。
    算法一般是传感器公司的私有产权。

    二、Android感应检测管理---SensorManager

    1、取得SensorManager


    使用感应检测Sensor首要先获取感应设备的检测信号,你可以调用Context.getSysteService(SENSER_SERVICE)方法来取得感应检测的服务

    2、实现取得感应检测Sensor状态的监听功能


    实现以下两个SensorEventListener方法来监听,并取得感应检测Sensor状态:

    //在感应检测到Sensor的精密度有变化时被调用到。   
    public void onAccuracyChanged(Senso sensor,int accuracy);  
    //在感应检测到Sensor的值有变化时会被调用到。   
    public void onSensorChanged(SensorEvent event);  

    3、实现取得感应检测Sensor目标各类的值

    实现下列getSensorList()方法来取得感应检测Sensor的值;
            List<Sensor> sensors = sm.getSensorList(Sensor.TYPE_TEMPERATURE);  

    4、注册SensorListener

    sm.regesterListener(SensorEventListener listener, Sensor sensor, int rate);  

            第一个参数:监听Sensor事件,第二个参数是Sensor目标种类的值,第三个参数是延迟时间的精度密度。延迟时间的精密度参数如下:

    参数

    延迟时间

    SensorManager.SENSOR_DELAY_FASTEST

    0ms

    SensorManager.SENSOR_DELAY_GAME

    20ms

    SensorManager.SENSOR_DELAY_UI

    60ms

    SensorManager.SENSOR_DELAY_NORMAL

    200ms

     

    因为感应检测Sensor的服务是否频繁和快慢都与电池参量的消耗有关,同时也会影响处理的效率,所以兼顾到消耗电池和处理效率的平衡,设置感应检测Sensor的延迟时间是一门重要的学问,需要根据应用系统的需求来做适当的设置。
    感应检测Sensor的硬件检测组件受不同的厂商提供。你可以采用Sensor的getVendor(),Sensor()的getName()和Sensor的getVeesrion()方法来取得 厂商的名称、产品和版本。

    5、取消注册

    sm.unregisterListener(SensorEventListener listener)  

    6、感应检测

    加速度感应检测——Accelerometer

    Accelerometer Sensor测量的是所有施加在设备上的力所产生的加速度的负值(包括重力加速度)。加速度所使用的单位是m/sec^2,数值是加速度的负值。

    SensorEvent.values[0]:加速度在X轴的负值
    SensorEvent.values[1]:加速度在Y轴的负值
    SensorEvent.values[2]:加速度在Z轴的负值

    例如:

    当手机Z轴朝上平放在桌面上,并且从左到右推动手机,此时X轴上的加速度是正数。

    当手机Z轴朝上静止放在桌面上,此时Z轴的加速度是+9.81m/sec^2。

    当手机从空中自由落体,此时加速度是0

    当手机向上以Am/sec^2的加速度向空中抛出,此时加速度是A+9.81m/sec^2

    重力加速度感应检测——Gravity

    重力加速度,其单位是m/sec^2,其坐标系与Accelerometer使用的一致。当手机静止时,gravity的值和Accelerometer的值是一致的。

    线性加速度感应检测——Linear-Acceleration

    Accelerometer、Gravity和Linear-Acceleration三者的关系如下公式:

    accelerometer = gravity + linear-acceleration

    地磁场感应检测——Magnetic-field

    地磁场的单位是micro-Tesla(uT),检测的是X、Y、Z轴上的绝对地磁场。

    陀螺仪感应检测——Gyroscope

    陀螺仪的单位是弧度/秒,测量的是物体分别围绕X,Y,Z轴旋转的角速度。它的坐标系与加速度传感器的坐标系相同。逆时针方向旋转的角度正的。也就是说,如果设备逆时针旋转,观察者向X,Y,Z轴的正方向看去,就报告设备是正转的。请注意,这是标准的正旋转的数学定义。

    光线感应检测——Light

    values[0]:表示环境光照的水平,单位是SI lux。

    位置逼近感应检测——Proximity

    values[0]:逼近的距离,单位是厘米(cm)。有一些传感器只能支持近和远两种状态,这种情况下,传感器必须报告它在远状态下的maximum_range值和在近状态下的小值。

    旋转矢量感应检测——Rotation Vector

    旋转向量是用来表示设备的方向,它是由角度和轴组成,就是设备围绕x,y,z轴之一旋转θ角度。旋转向量的三个要素是,这样旋转向量的大小等于sin(θ/2),旋转向量的方向等于旋转轴的方向。

    values[0]: x*sin(θ/2) 
    values[1]: y*sin(θ/2) 
    values[2]: z*sin(θ/2) 
    values[3]: cos(θ/2) (optional: only if value.length = 4)

    方向感应检测——Orientation

    其单位是角度

    values[0]: Azimuth(方位),地磁北方向与y轴的角度,围绕z轴旋转(0到359)。0=North, 90=East, 180=South, 270=West 
    values[1]: Pitch(俯仰),围绕X轴旋转(-180 to 180), 当Z轴向Y轴运动时是正值
    values[2]: Roll(滚),围绕Y轴旋转(-90 to 90),当X轴向Z轴运动时是正值 

    三、举例之-Gsensor

    1,图示三轴方向

    android重力感应系统的坐标系以屏幕的左下方为原点(【注意】2d编程的时候,是以屏幕左上方为原点的),箭头指向的方向为正。从-10到10,以浮点数为等级单位,想象一下以下情形:

      手机屏幕向上(z轴朝天)水平放置的时侯,(x,y,z)的值分别为(0,0,10);
      手机屏幕向下(z轴朝地)水平放置的时侯,(x,y,z)的值分别为(0,0,-10);
      手机屏幕向左侧放(x轴朝天)的时候,(x,y,z)的值分别为(10,0,0);
      手机竖直(y轴朝天)向上的时候,(x,y,z)的值分别为(0,10,0);
      其他的如此类推,规律就是:朝天的就是正数,朝地的就是负数。利用x,y,z三个值求三角函数,就可以精确检测手机的运动状态了。

    2,通过监测Gsensor判断手机处于静止/移动状态

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. public class MainActivity extends Activity implements SensorEventListener {  
    2.   
    3.     private static final String TAG = MainActivity.class.getSimpleName();  
    4.     private SensorManager mSensorManager;  
    5.     private Sensor mSensor;  
    6.     private TextView textviewX;  
    7.     private TextView textviewY;  
    8.     private TextView textviewZ;  
    9.     private TextView textviewF;  
    10.   
    11.     private int mX, mY, mZ;  
    12.     private long lasttimestamp = 0;  
    13.     Calendar mCalendar;  
    14.   
    15.     @Override  
    16.     protected void onCreate(Bundle savedInstanceState) {  
    17.         super.onCreate(savedInstanceState);  
    18.         setContentView(R.layout.activity_main);  
    19.         textviewX = (TextView) findViewById(R.id.textView1);  
    20.         textviewY = (TextView) findViewById(R.id.textView3);  
    21.         textviewZ = (TextView) findViewById(R.id.textView4);  
    22.         textviewF = (TextView) findViewById(R.id.textView2);  
    23.   
    24.         mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);  
    25.         mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);// TYPE_GRAVITY  
    26.         if (null == mSensorManager) {  
    27.             Log.d(TAG, "deveice not support SensorManager");  
    28.         }  
    29.         // 参数三,检测的精准度  
    30.         mSensorManager.registerListener(this, mSensor,  
    31.                 SensorManager.SENSOR_DELAY_NORMAL);// SENSOR_DELAY_GAME  
    32.   
    33.     }  
    34.   
    35.     @Override  
    36.     public void onAccuracyChanged(Sensor sensor, int accuracy) {  
    37.   
    38.     }  
    39.   
    40.     @Override  
    41.     public void onSensorChanged(SensorEvent event) {  
    42.         if (event.sensor == null) {  
    43.             return;  
    44.         }  
    45.   
    46.         if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {  
    47.             int x = (int) event.values[0];  
    48.             int y = (int) event.values[1];  
    49.             int z = (int) event.values[2];  
    50.             mCalendar = Calendar.getInstance();  
    51.             long stamp = mCalendar.getTimeInMillis() / 1000l;// 1393844912  
    52.   
    53.             textviewX.setText(String.valueOf(x));  
    54.             textviewY.setText(String.valueOf(y));  
    55.             textviewZ.setText(String.valueOf(z));  
    56.   
    57.             int second = mCalendar.get(Calendar.SECOND);// 53  
    58.   
    59.             int px = Math.abs(mX - x);  
    60.             int py = Math.abs(mY - y);  
    61.             int pz = Math.abs(mZ - z);  
    62.             Log.d(TAG, "pX:" + px + "  pY:" + py + "  pZ:" + pz + "    stamp:"  
    63.                     + stamp + "  second:" + second);  
    64.             int maxvalue = getMaxValue(px, py, pz);  
    65.             if (maxvalue > 2 && (stamp - lasttimestamp) > 30) {  
    66.                 lasttimestamp = stamp;  
    67.                 Log.d(TAG, " sensor isMoveorchanged....");  
    68.                 textviewF.setText("检测手机在移动..");  
    69.             }  
    70.   
    71.             mX = x;  
    72.             mY = y;  
    73.             mZ = z;  
    74.   
    75.         }  
    76.     }  
    77.   
    78.     /** 
    79.      * 获取一个最大值 
    80.      *  
    81.      * @param px 
    82.      * @param py 
    83.      * @param pz 
    84.      * @return 
    85.      */  
    86.     public int getMaxValue(int px, int py, int pz) {  
    87.         int max = 0;  
    88.         if (px > py && px > pz) {  
    89.             max = px;  
    90.         } else if (py > px && py > pz) {  
    91.             max = py;  
    92.         } else if (pz > px && pz > py) {  
    93.             max = pz;  
    94.         }  
    95.   
    96.         return max;  
    97.     }  
    98. }  

    原理就是通过每次得到的x,y,z三轴的值,和下一次的值作比较,它们每个差值中绝对值最大的如果超过某一个阀值(自己定义),并且这种状态持续了x秒,我们就视为手机处于(颠簸)移动状态,当然这种判断肯定是不科学的,有时候也会产生误判,比较理想的场景就是:携带手机坐在公交上或是开车。

    其它可供参考资料:

    http://blog.csdn.net/zhandoushi1982/article/details/8591878 

    http://blog.csdn.net/ZhengZhiRen/article/details/5930451

    http://blog.csdn.net/a345017062/article/details/6459643

  • 相关阅读:
    Charles:rewrite重写功能
    Vue中provide和inject 用法
    vue中install方法
    vue自定义组件(通过Vue.use()来使用)即install的使用
    Eelectron 中的remote模块
    理解Vue中的Render渲染函数
    Vue.js中this.$nextTick()的使用
    postman请求本地接口Error: connect ECONNREFUSED 127.0.0.1:8083
    1016 Phone Bills (25 分)
    CF842E Nikita and game
  • 原文地址:https://www.cnblogs.com/exmyth/p/4626224.html
Copyright © 2020-2023  润新知