文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处http://blog.csdn.net/flowingflying/以及作者@恺风Wei

陀螺仪

陀螺仪(Gyroscope sensor)测量设备转动的角速度。最早的陀螺仪发明在中国,科学应用则在西方,陀螺仪是为士大夫坐轿子看书是免收烛光摇曳发明的,这在很久之前一部西方拍的科教片看到,具体名字忘了。Pro Android 4.0中说陀螺仪的误差会慢慢积累,因此通与加速传感器一致使用,通过Kalman
filter进行修正。我们只简单地进行陀螺仪数据的读取。小例子和之前的很相似,我们只提供不同部分的代码片段。

public class GyroscopeSensorActivity extends Activity implements SensorEventListener{ 

    ……      

    @Override 

    protected void onCreate(Bundle savedInstanceState) {  

        …… 

        sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); 

        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); 

    } 

    

    …… //注册和注销传感器的监听器

   @Override 

    public void onAccuracyChanged(Sensor sensor, int accuracy) {  …  }

    @Override  /* 对于陀螺仪,测量的是x、y、z三个轴向的角速度,分别从values[0]、values[1]、values[2]中读取,单位为弧度/秒。*/
    public void onSensorChanged(SensorEvent event) { 

        if(event.sensor.getType() == Sensor.TYPE_GYROSCOPE)

            showInfo("事件:" + " x:" + event.values[0] + " y:" + event.values[1]  + " z:" + event.values[2]);

    } 

    

    //在华为P6的机器上,陀螺仪非常敏感,平放在桌面,由于电脑照成的轻微震动在不断地刷屏,为了避免写UI造成的性能问题,只写Log。

    private void showInfo(String info){ 

        //tv.append("\n" + info); 

        Log.d("陀螺仪",info); 

    } 

}

加速度传感器(acceleration)

加速度测量传感器有x、y、z三轴,注意和2D屏幕的坐标,以左上角作为原点的,而且Y向下。注意区分这两个不同的坐标系。

加速传感器的单位是加速度m/s2。如果手机平放好,x,y在位置为0,而z轴方向加速度=当前z方向加速度-g。由于g(重力加速度)垂直向下,则g=-9.81m/s2,即z轴 a=0-(-9.81)=9.81m/s2。也就是自由落体是为0。x、y、z的测量的加速度分别位于value[0]、value[1]、value[2]。

相关的代码和前面大同小异,我们就不再重复,传感器类型为Sensor.TYPE_ACCELEROMETER。减去重力这很重要,当设备静止或者匀速运动时,可以获得设备的角度。

我记得至少两年前,单位请一互联网专家讲课,提到了AR(增强现实),问靠什么传感器,其答案为陀螺仪,这是不对的,陀螺仪可以测量运动过程中的角速度,但要测量手机本身的角度,这靠的是加速仪器,因为有重力方向作为校准。

Android也提供了检测手机旋转角度的API,用于UI绘制,实际靠的就是加速传感器。

WindowManager window = (WindowManager)getSystemService(WINDOW_SERVICE); 
//返回值为Surface.ROTATION_0(0)、Surface.ROTATION_90(1)、Surface.ROTATION_180(2)和Surface.ROTATION_270(3),可以用来确定屏幕UI的旋转方向。注意:需要开启“自动旋转”才能有效检查,否则均为Surface.ROTATION_0(手机以竖屏为主,一般都会0,但不保证都如此)。不是所以的手机都能检测到这4个值,例如我的P6,没有Surface.ROTATION_180,即UI不支持倒过来,如果有某个数值不支持,通过getRotation()获取的数值可能并不准确,仍以P6为例,如果我们顺时针转90°,得到Surface.ROTATION_90,继续顺时针转至180°,无检测新数值,仍未Surface.ROTATION_90,再继续顺时针转90°(至270°),仍显示为Surface.ROTATION_90,而非Surface.ROTATION_270。

int rotation = window.getDefaultDisplay().getRotation(); //在Android2.2之前,为Display.getOrientation(),如果出现API和SDK 的API level相关,可通过Build.VERSION.SDK_INT获得。

我们将手机平放在桌子上,通过加速度测量仪的x、y、z轴的数值,x、y为0,z为g,可以进行判断,但是我们并不知道具体的朝向,平放是朝南还是向北,这需要地磁感应器,将在后面介绍。

下面的小例子,我们将对加速度测量仪的x,y,z数值进行修正处理,减去重力加速度,得到我们这个惯性系的加速度,并根据设备的Y轴与垂直地面方向(重力反方向)的夹角。相关的代码片段如下:

……

private float[] gravity = new float[3];   //重力在设备x、y、z轴上的分量

private float[] motion = new float[3];  //过滤掉重力后,加速度在x、y、z上的分量
private double ratioY; 

private double angle; 

private int counter = 1; 

@Override 

public void onSensorChanged(SensorEvent event) {  

    for(int i = 0 ; i < 3; i ++){ 

        /* accelermeter是很敏感的,看之前小例子的log就知道。因为重力是恒力,我们移动设备,它的变化不会太快,不象摇晃手机这样的外力那样突然。因此通过low-pass filter对重力进行过滤。这个低通滤波器的权重,我们使用了0.1和0.9,当然也可以设置为0.2和0.8。 */

        gravity[i] = (float) (0.1 * event.values[i] + 0.9 * gravity[i]); 

        motion[i] = event.values[i] - gravity[i]; 

    } 

    

    //计算重力在Y轴方向的量,即G*cos(α) 

    ratioY = gravity[1]/SensorManager.GRAVITY_EARTH; 

    if(ratioY > 1.0) 

        ratioY = 1.0; 

    if(ratioY < -1.0) 

        ratioY = -1.0; 

    //获得α的值,根据z轴的方向修正其正负值。 
    angle = Math.toDegrees(Math.acos(ratioY)); 

    if(gravity[2] < 0) 

        angle = - angle; 

    

    //避免频繁扫屏,每10次变化显示一次值 

    if(counter ++ % 10 == 0){ 

        tv.setText("Raw Values : \n" 

                +  "   x,y,z = "+ event.values[0] + "," + event.values[1] + "," + event.values[2] + "\n"

                +  "Gravity values : \n" 

                +  "   x,y,z = "+ gravity[0] + "," + gravity[1] + "," + gravity[2] + "\n"

                +  "Motion values : \n" 

                +  "   x,y,z = "+ motion[0] + "," + motion[1] + "," + motion[2] + "\n"

                +  "Y轴角度 :" + angle    ); 

        tv.invalidate(); 

        counter = 1; 

    }     



……

motion[3]是过滤重力后的数值,如果各值如果非常接近0,表示设备没有被移动。

Pro Android学习笔记(一五四):传感器(4):陀螺仪、加速传感器的更多相关文章

  1. 【转】 Pro Android学习笔记(五四):调试和分析(2):View层次结构

    目录(?)[-] 帮助性能分析 帮助精简UI设计 对于模拟器上的应用(非真实设备),可以查看Hierarchy View,如下图: 帮助性能分析 当我们选择某个view时,我们可以看到measurin ...

  2. 【转】 Pro Android学习笔记(七七):服务(2):Local Service

    目录(?)[-] Local service代码 调用Local ServiceLocal Service client代码 AndroidManifestxml定义Serviceacitivty的l ...

  3. 【转】 Pro Android学习笔记(二九):用户界面和控制(17):include和merge

    目录(?)[-] xml控件代码重用include xml控件代码重用merge 横屏和竖屏landsacpe portrait xml控件代码重用:include 如果我们定义一个控件,需要在不同的 ...

  4. 【转】Pro Android学习笔记(十二):了解Intent(下)

    解析Intent,寻找匹配Activity 如果给出component名字(包名.类名)是explicit intent,否则是implicit intent.对于explicit intent,关键 ...

  5. Pro Android学习笔记 ActionBar(1):Home图标区

     Pro Android学习笔记(四八):ActionBar(1):Home图标区 2013年03月10日 ⁄ 综合 ⁄ 共 3256字 ⁄ 字号 小 中 大 ⁄ 评论关闭 ActionBar在A ...

  6. 【转】 Pro Android学习笔记(八二):了解Package(1):包和进程

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在之前,我们已经学习了如何签发apk,见P ...

  7. 【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET

    目录(?)[-] HTTP GET小例子 简单小例子 出现异常NetworkOnMainThreadException 通过StrictMode进行处理 URL带键值对 Andriod应用可利用ser ...

  8. 【转】 Pro Android学习笔记(五五):调试和分析(3):adb命令、模拟器控制台和StrictMode

    目录(?)[-] adb命令 模拟器Console StrictMode adb命令 我们在学习SQLite的使用,介绍过部分adb命令的使用,见Pro Android学习笔记(五):了解Conten ...

  9. 【转】 Pro Android学习笔记(五六):配置变化

    目录(?)[-] Activity的destorycreate过程 Fragment的destorycreate过程 onSaveInstanceState saveFragmentInstanceS ...

  10. 【转】 Pro Android学习笔记(五二):ActionBar(5):list模式

    可以在action bar中加入spinner的下来菜单,有关spinner,可以参考Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner. list的样式和 ...

随机推荐

  1. C#高级编程七十五天----C#使用指针

    在C#中使用指针的语法 假设想在C#中使用指针,首先对项目进行过配置: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/font ...

  2. 操作系统 资源管理 zookeeper yarn 进程管理 分布式 yarn诞生背景

    zookeeper 信息保管员 YARN 简介 https://www.ibm.com/developerworks/cn/data/library/bd-yarn-intro/index.html

  3. tornado之异步web服务二

    前面介绍了异步方法带来的显著性能提升.我们来看下异步使用的方法. 1 首先对于get方法使用tornado.web.asynchronous进行装饰.当使用tornado.web.asynchrono ...

  4. DNS常见攻击与防范

    DNS常见攻击与防范 转自:http://www.williamlong.info/archives/3813.html 日期:2015-7-10 随着网络的逐步普及,网络安全已成为INTERNET路 ...

  5. vsftp登录时间太长的解决办法

    与ssh一样,vsftp的配置文件默认开启了DNS反向解析,这可能会造成用户在登陆到FTP服务器的时候奇慢无比,只要在配置文件中禁用DNS反向解析即可解决文件. 编辑/etc/vsftpd/vsftp ...

  6. BestCoder7 1002 Little Pony and Alohomora Part I(hdu 4986) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4986 题目意思:有 n 个box(从左到右编号依次为1~n),每个box里面有一个随机的钥匙,有可能这 ...

  7. 常用的PHP类库,PHP开发者必备【转】

    PHP开发者常用的PHP类库和组件 PDF 生成器 FPDF - 这量一个可以让你生成PDF的纯PHP类库. Excel 相关 你的站点需要生成Excel?没有问题,下面这两个类库可以让你轻松做到这一 ...

  8. Linux-awk和shell编程初步

    1 awk 格式: awk -选项 '处理' 输入 awk -F : '{print $1}' file -F指定分隔符, 默认是空格 $1 分割后的第一部分 $0 获得所有部分 NF 表示以分隔符分 ...

  9. Asterisk 通话过程中执行动作(即applicationmap )的使用方法和电话转会议的实现

      asterisk在正常通话过程中执行拨号计划中动作是通过feature.conf中的[applicationmap ]下定义的,举例如下: nway-start => *0,callee,M ...

  10. springmvc配置一:ajax请求防止返回中文乱码配置说明

    Spring3.0 MVC @ResponseBody 的作用是把返回值直接写到HTTP response body里. Spring使用AnnotationMethodHandlerAdapter的 ...