文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处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. MSQL Webpage

    Mars Nov 19, 2014

  2. 计算IMEI号的校验位

    计算IMEI号的校验位 移动设备国际识别码(IMEI:International Mobile Equipment Identification Number)是差别移动设备的标志,具有唯一性,贴在手 ...

  3. ASP.NET车辆管理系统100%源代码

    系统开发环境为VS2010.採用ASP.NET框架.数据库採用SQL Server.系统採用Ajax,具有:GPS导航(实时监控报警).申请审核.流程查看及短信息发送等功能.这个系统界面和功能是我认为 ...

  4. SAM4E单片机之旅——8、UART初步

    通信还是比让LED灯闪烁实用得多的. 这次试试使用UART,实现开发版和PC间的通信.功能比较简单,就是把PC发向开发版的内容发送回去.这次主要介绍一下UART的配置,至于通信,则使用较为简单的不断查 ...

  5. EasyRTMP实现对接海康、大华等IPCamera SDK进行RTMP推送直播功能

    本文转自EasyDarwin团队Kim的博客:http://blog.csdn.net/jinlong0603 Demo项目介绍 EasyRTMP Demo代码下载地址https://github.c ...

  6. 如何缓存hbase数据以减少下次取数据的时间

    缓存从hbase取得的数据的好处是显而易见的,缓存到本地以后,如果下次的输入能够直接从已缓存的本地文件中取得数据就无需再次访问hbase数据库,这样一来数据量大的话可以节省大量的访问hbase数据库的 ...

  7. div和span、relative和absolute、display和visibility的区别

    一.div和span的区别 div是一个块级元素,可以包含段落,表格等内容,用于放置不同的内容.一般我们在网页通过div来布局定位网页中的每个区块. span是一个内联元素,没有实际意义,它的存在纯粹 ...

  8. 渲染树render tree

    CSSOM树和DOM树连接在一起形成一个render tree,渲染树用来计算可见元素的布局并且作为将像素渲染到屏幕上的过程的输入. DOM树和CSSOM树连接在一起形成render tree . r ...

  9. <十四>UML核心视图静态视图之类图和包图

    一:类图(行为类和实体类) --->类图用于展示系统中的类及其相互之间的关系 --->概念层类图 --->说明层类图   二:概念层类图 --->概念层的观点认为:在这个层次的 ...

  10. LiveCD、LiveDVD和BinDVD区别在哪里

    本文转载自: http://www.kankanews.com/ICkengine/archives/86968.shtml 1.CentOS系统镜像有两个,安装系统只用到第一个镜像即CentOS-6 ...