Pro Android学习笔记(一五四):传感器(4):陀螺仪、加速传感器
文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处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):陀螺仪、加速传感器的更多相关文章
- 【转】 Pro Android学习笔记(五四):调试和分析(2):View层次结构
目录(?)[-] 帮助性能分析 帮助精简UI设计 对于模拟器上的应用(非真实设备),可以查看Hierarchy View,如下图: 帮助性能分析 当我们选择某个view时,我们可以看到measurin ...
- 【转】 Pro Android学习笔记(七七):服务(2):Local Service
目录(?)[-] Local service代码 调用Local ServiceLocal Service client代码 AndroidManifestxml定义Serviceacitivty的l ...
- 【转】 Pro Android学习笔记(二九):用户界面和控制(17):include和merge
目录(?)[-] xml控件代码重用include xml控件代码重用merge 横屏和竖屏landsacpe portrait xml控件代码重用:include 如果我们定义一个控件,需要在不同的 ...
- 【转】Pro Android学习笔记(十二):了解Intent(下)
解析Intent,寻找匹配Activity 如果给出component名字(包名.类名)是explicit intent,否则是implicit intent.对于explicit intent,关键 ...
- Pro Android学习笔记 ActionBar(1):Home图标区
Pro Android学习笔记(四八):ActionBar(1):Home图标区 2013年03月10日 ⁄ 综合 ⁄ 共 3256字 ⁄ 字号 小 中 大 ⁄ 评论关闭 ActionBar在A ...
- 【转】 Pro Android学习笔记(八二):了解Package(1):包和进程
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在之前,我们已经学习了如何签发apk,见P ...
- 【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET
目录(?)[-] HTTP GET小例子 简单小例子 出现异常NetworkOnMainThreadException 通过StrictMode进行处理 URL带键值对 Andriod应用可利用ser ...
- 【转】 Pro Android学习笔记(五五):调试和分析(3):adb命令、模拟器控制台和StrictMode
目录(?)[-] adb命令 模拟器Console StrictMode adb命令 我们在学习SQLite的使用,介绍过部分adb命令的使用,见Pro Android学习笔记(五):了解Conten ...
- 【转】 Pro Android学习笔记(五六):配置变化
目录(?)[-] Activity的destorycreate过程 Fragment的destorycreate过程 onSaveInstanceState saveFragmentInstanceS ...
- 【转】 Pro Android学习笔记(五二):ActionBar(5):list模式
可以在action bar中加入spinner的下来菜单,有关spinner,可以参考Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner. list的样式和 ...
随机推荐
- 基于chyh1990/caffe-compact在windows vs2013上编译caffe步骤
1. 从https://github.com/chyh1990/caffe-compact下载caffe-compact代码: 2. 通过CMake(cmake-gui)生成vs2 ...
- php 去除html标记-strip_tags和htmlspecialchars的区别
strip_tags 去掉 HTML 及 PHP 的标记. 语法: string strip_tags(string str); 传回值: 字串 函式种类: 资料处理 内容说明 本函式可去掉字串中包含 ...
- SVN经常使用命令总结(持续更新)
如今流行的协同管理工具预计就属SVN和Git了.这两者都使用过,只是如今正在使用的是SVN.故将常常使用的命令总结下来. 无论是Windows端的svnclient还是eclipse的subversi ...
- RecyclerView的那点事儿
RecyclerView 控件简单介绍 ListView的升级版 LinearLayoutManager GridLayoutManager StaggeredGridLayoutManager 定制 ...
- 九度OJ 1101:计算表达式 (DP)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4340 解决:1335 题目描述: 对于一个不存在括号的表达式进行计算 输入: 存在多种数据,每组数据一行,表达式不存在空格 输出: 输出结 ...
- vue http 请求
https://github.com/vuejs/awesome-vue#http-requests vue-resource - npm https://www.npmjs.com/package/ ...
- exp/imp三种模式——完全、用户、表
ORACLE数据库有两类备份方法.第一类为物理备份,该方法实现数据库的完整恢复,但数据库必须运行在归挡模式下(业务数据库在非归挡模式下运行),且需要极大的外部存储设备,例如磁带库:第二类备份方式为逻辑 ...
- Tomcat Session Clustering
搭建 Tomcat 集群需要解决很多的问题,其中之一就是要解决 Session 共享问题.小规模集群可以使用 Tomcat 提供的 Session Clustering 来解决. For the im ...
- linux内核container_of宏定义分析
看见一个哥们分析container_of很好,转来留给自己看 一.#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMB ...
- jquery特效(4)—轮播图②(定时自动轮播)
周末出去逛完街,就回公司好好地研究代码了,也算是把定时自动轮播程序写出来了,特意说明一下,这次的轮播图是在昨天随笔中jquery特效(3)—轮播图①(手动点击轮播)的基础上写出来的,也就是本次随笔展示 ...