Android 推荐使用SensorManager的加速度传感器和磁场传感器配合使用,实现指南针。

垂直手机屏幕那一面向上为Z轴,向右为x,垂直于XZ面的即为Y轴

具体步骤如下:

1.注册SensorManager,获取当前设备的传感器列表,查看是否含有加速度传感器和磁场强度传感器。如果确认设备中一定含有加速度传感器和磁场强度传感器可以不获取sensorList。

SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor : sensorList) {Log.w(TAG, "SensorHelper: ===" + sensor.getStringType());
}

2.获取地磁传感器和加速度传感器并订阅监听,并在onDestroy()中取消监听。

//地磁感应器
Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
//加速度感应器
Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, magneticSensor, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(this, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
@Overrideprotected void onDestroy() {super.onDestroy();if (sensorManager != null) {sensorManager.unregisterListener(this);}}

3.自定义监听实现接口:SensorEventListener。在onSensorChanged中增加了低通滤波,可以降低抖动。

@Overridepublic void onSensorChanged(SensorEvent event) {final float alpha = 0.97f;// 判断当前是加速度感应器还是地磁感应器if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {//赋值调用clone方法
//            accelerometerValues = event.values.clone();accelerometerValues[0]=alpha * accelerometerValues[0] + (1 - alpha) * event.values[0];accelerometerValues[1]=alpha * accelerometerValues[1] + (1 - alpha) * event.values[1];accelerometerValues[2]=alpha * accelerometerValues[2] + (1 - alpha) * event.values[2];} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {//赋值调用clone方法
//            magneticValues = event.values.clone();magneticValues[0]=alpha * magneticValues[0] + (1 - alpha) * event.values[0];magneticValues[1]=alpha * magneticValues[1] + (1 - alpha) * event.values[1];magneticValues[2]=alpha * magneticValues[2] + (1 - alpha) * event.values[2];}float[] R = new float[9];float[] I = new float[9];float[] values = new float[3];boolean success=SensorManager.getRotationMatrix(R,I,accelerometerValues,magneticValues);sensorManager.getOrientation(R, values);
//【2.2】根据inclination matrix计算磁仰角,地球表面任一点的地磁场总强度的矢量方向与水平面的夹角。double mInclination = SensorManager.getInclination(I);
//        Log.i(TAG, "onSensorChanged: -----磁场强度:"+henceValue);
//        Log.d("Main","values[0] :"+Math.toDegrees(values[0]));//values[0]的取值范围是-180到180度。//将计算出的旋转角度取反,用于旋转指南针背景图//+-180表示正南方向,0度表示正北,-90表示正西,+90表示正东int mAzimuth = (int) Math.toDegrees(values[0]);int valueNew,valueNew1;if (mAzimuth < 0) {valueNew = mAzimuth + 360;} else {valueNew = mAzimuth;}float SmoothFactorCompass = 0.95f;float SmoothThresholdCompass = 10.0f;if(Math.abs(compassNumber-valueNew)<180){if(Math.abs(compassNumber-valueNew)>SmoothThresholdCompass){valueNew1=valueNew;}else {valueNew1 = (int) (compassNumber + SmoothFactorCompass * (valueNew - compassNumber));}}else{if (360.0 - Math.abs(valueNew - compassNumber) > SmoothThresholdCompass) {valueNew1 = valueNew;}else {if (compassNumber > valueNew) {valueNew1 = (int) ((compassNumber + SmoothFactorCompass * ((360 + valueNew - compassNumber) % 360) + 360) % 360);} else {valueNew1 = (int) ((compassNumber - SmoothFactorCompass * ((360 - valueNew + compassNumber) % 360) + 360) % 360);}}}if (Math.abs(compassNumber-valueNew1)>=1 && success) {
//        if ( success) {compassNumber = valueNew1;pitchNumber= (int) Math.toDegrees(values[1]);//俯仰角rollNumber= (int) Math.toDegrees(values[2]);//横滚角elevationNumber= (int) Math.toDegrees(mInclination);henceValue= (int)((I[3]*R[0]+I[4]*R[3]+I[5]*R[6])*magneticValues[0]+(I[3]*R[1]+I[4]*R[4]+I[5]*R[7])*magneticValues[1]+(I[3]*R[2]+I[4]*R[5]+I[5]*R[8])*magneticValues[2]);Log.i(TAG, "onSensorChanged: magneticValues:"+ Arrays.toString(magneticValues)+"_____accelerometerValues:"+ Arrays.toString(accelerometerValues));mHandler.removeMessages(MESSAGE_UPDATE_COMPASSNUMBER);mHandler.sendEmptyMessage(MESSAGE_UPDATE_COMPASSNUMBER);//更新指南针}}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {//        Log.i(TAG, "onAccuracyChanged: accuracy0:"+accuracy+"____sensor0:"+sensor.getStringType());if(sensor.getType()== Sensor.TYPE_MAGNETIC_FIELD){accuracyValue=accuracy;sensorType=sensor.getStringType();Log.i(TAG, "onAccuracyChanged: accuracy:"+accuracy+"____sensor:"+sensor.getStringType());mHandler.removeMessages(MESSAGE_UPDATE_COMPASSNUMBER_ACCURACY);mHandler.sendEmptyMessage(MESSAGE_UPDATE_COMPASSNUMBER_ACCURACY);//更新指南针精度}}

4. 踩坑介绍:

开发板上默认都是竖屏,陀螺仪(G-Sensor)和地磁传感器(E-compass)的方向设置也是默认竖屏。项目中要求是横屏使用,硬件工程师将地磁传感器横屏摆放,陀螺仪也按照高通推荐设置,但是最后使用时,发现水平状态测出的指南针数据正常。当时开发板竖直过程中,数据明显异常。

最后发现是加速度传感器的x,y轴方向的系统设置问题。设备的陀螺仪1pin对着主板的右上角,开发板的陀螺仪的1pin对着主板的左上角,查看俯仰角和横滚角,发现当前设备的横纵坐标需要逆时针旋转90°才能和原本开发板的方向一致。

有两种方案,方案一,改apk的加速度传感器的角度,原本代码如下:

public void onSensorChanged(SensorEvent event) {final float alpha = 0.97f;// 判断当前是加速度感应器还是地磁感应器if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {//赋值调用clone方法accelerometerValues = event.values.clone();}

修改后代码如下:

if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {//赋值调用clone方法
//            accelerometerValues = event.values.clone();accelerometerValues[0]=event.values[1];accelerometerValues[1]=-event.values[0];accelerometerValues[2]= event.values[2];}

方案2,系统修改x轴和y轴,在/vendor/qcom/proprietary/sensors-see/registry/config/lito目录下,

修改 lito_bmi160_0-2.json 中orient部分的代码如下:

 ".orient":{"owner": "sns_bmi160","x":{ "type": "str", "ver": "0","data": "x"},"y":{ "type": "str", "ver": "0","data": "y"},"z":{ "type": "str", "ver": "0","data": "+z"}},

最终效果:

完整代码:豆子就是我/compass - 码云 - 开源中国 (gitee.com)

参考博客:

(137条消息) Android 指南针校正_Wezarp的博客-CSDN博客_android 指南针校准

(137条消息) Android传感器 设备坐标系到世界坐标系的转换 分析以及应用_pwwwwwok的博客-CSDN博客

(137条消息) android 指南针不稳定,Android指南针方向不可靠(低通滤波器)_weixin_39562234的博客-CSDN博客(137条消息) Android 磁场传感器 地磁倾角计算 SensorManager.getInclination方法_pwwwwwok的博客-CSDN博客_android 地磁

Android 高通平台指南针跳变,竖起过程数据不准,Android getRotationMatrix和getOrientation使用记录相关推荐

  1. android 高通平台有前途吗,华为鸿蒙计划要适配高通平台了,可以告别安卓搭载鸿蒙OS了?...

    鸿蒙走出这一步是可以想象到的,看来华为打造这个系统希望的结果是万物皆可盘呀,所以一开始就提出了开源,也就意味着这次是高通,下次就可以是联发科,甚至更多的手机品牌也完全就可以搭载!早期我们一直在说国产手 ...

  2. Android高通平台调试Camera驱动全纪录

    项目比较紧,3周内把一个带有外置ISP,MIPI数据通信,800万像素的camera从无驱动到实现客户全部需求. 1日 搭平台,建环境,编译内核,烧写代码. 我是一直在Window下搭个虚拟机登服务器 ...

  3. 请把Camera hold住 - Android高通平台调试Camera驱动全纪录

    项目比较紧,3周内把一个带有外置ISP,MIPI数据通信,800万像素的camera从无驱动到实现客户全部需求. 1日 搭平台,建环境,编译内核,烧写代码. 我是一直在Window下搭个虚拟机登服务器 ...

  4. android+高通平台缩写汇聚

    1.音频部分 Low Power Audio Subsystem (LPASS)低功耗音频子系统 Audio Calibration Database (ACDB)音频校准数据库 Audio Fron ...

  5. Android系统高通平台新增lunch选项

    Android系统高通平台新增lunch选项 创建xxx目录 device/qcom/xxx 目录里添加必要的内容 device/qcom/common/vendorsetup.sh添加 add_lu ...

  6. Android 8/9高通平台客制化虚拟导航按键隐藏

    高通平台源代码更改 diff --git a/frameworks/base/packages/SystemUI/res/values/config.xml b/frameworks/base/pac ...

  7. android 4.4.2 去除漫游r,Android 4.4.3应用,高通平台 去掉应用

    android 4.4.3 高通平台那些apk android 一 .packages/apps BasicMmsReceiver Bluetooth Browser Calculator Calen ...

  8. 高通平台环境搭建,编译,系统引导流程分析 .

    1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通开发板上烧录文件系统 建立高通平台开发环境 高通平台,android和 modem 编译流程分析 高通平台 7620 启动流 ...

  9. 高通平台耳机类型识别

    耳机类型 耳机类型一般有两种:3段式耳机和4段式耳机.其中4段式耳机又分为欧标和美标. 3段耳机:线序分别为,L,R,G,没有MIC端,所以三段耳机无法使用麦克风,只能接受声音,另外,三段耳机L,R线 ...

  10. 高通平台耳机知识记录

    一. 在高通平台中,默认使用内部codec的时候,耳机的输出及控制都是在内部codec中进行的,所以,可以想象得到,耳机的整个初始化起源过程,是在codec的初始化中.高通平台的machine驱动文件 ...

最新文章

  1. android 获取视频大小,Android 获取视频缩略图(获取视频每帧数据)的优化方案
  2. ascii码_umask,补码,ASCII码:稍微深入考虑一点
  3. php 字符串转换xml,php 数组转xml字符串、xml字符串转数组方法案例
  4. 一个Demo展示Storyboard的强大
  5. android 蓝牙编程重点---如何发送和接收16进制数据
  6. 2015年传智播客java_2015年最佳Java教程
  7. 2022快手春节集卡活动 集好运中国福活动攻略
  8. 贝尔曼方程怎么解_哈密顿-雅可比-贝尔曼方程
  9. 景区门票预约系统_无预约,不出游!免费景区门票赶紧预约~
  10. 在delphi中制作二维码
  11. Keytool生成数字证书 + Tomcat https 配置
  12. 图解对称加密与非对称加密
  13. 【linux虚拟机使用yum安装MySQL+修改密码】
  14. iperf安装与使用
  15. 第15章 嵌入式SQL的应用
  16. Android基础入门教程——8.3.18 Canvas API详解(Part 3)Matrix和drawBitmapMash
  17. Tomcat Ajp(CVE-2020-1938) 漏洞复现与修复
  18. 精品国创《少年歌行》数字藏品开售,邀你共铸少年武侠江湖梦
  19. 智课雅思词汇---十七、前綴il-, in-, ir-, im-有什麼關係
  20. 视觉SLAM中的数学——解方程AX=b与矩阵分解:奇异值分解(SVD分解) 特征值分解 QR分解 三角分解 LLT分解

热门文章

  1. WIN7系统电脑关机后自动重启解决方法
  2. 用HTML写一首绝句古诗,唐诗七绝绝句经典50首:唐诗七绝悲伤的句子让人心醉
  3. 12306系统升级对电力营销系统改造的启示
  4. TEXT到EPUB格式转换
  5. wincc逻辑运算符_wincc中表达式及公式
  6. 利用树制作的简易家谱
  7. CS5211:DP/eDP to 2Port LVDS
  8. 小红花代表什么_送你一朵小红花讲述的是什么样的故事 剧情全介绍
  9. 三角形内切圆 / 外接圆半径计算公式及证明总结 ~
  10. 数据集中趋势度量:众数、平均数、中位数、几何平均数