第一次写博客,非常的担心自己的表达能力不足造成大家的不便,如有不便请谅解,我会继续努力。写出更高质量更好的博客分享。
本人的公司是做无人机的,之前采用手机获取经纬度的数据给飞控进行跟随功能的开发,但是公司觉得还是需要提高无人机跟随的灵敏度,并且希望在gps信号不好的情况下还能进行一定程度的跟随,所以在跟飞控工程师的协商下,获取了手机的方向传感器跟加速度传感器。具体的方向传感器的意义可以参考此链接:https://my.oschina.net/airship/blog/383047 加速度传感器的意义可以参考此链接:http://blog.csdn.net/lincyang/article/details/49471929
通过飞控工程师给的算法计算出了正东,正北与向下的加速度。
首先获取传感器的实例并且设置监听:
private SensorManager sensorManager; private Sensor acc_sensor; private Sensor mag_sensor;
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); acc_sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); mag_sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); //给传感器注册监听: sensorManager.registerListener(this, acc_sensor, SensorManager.SENSOR_DELAY_GAME); sensorManager.registerListener(this, mag_sensor,SensorManager.SENSOR_DELAY_GAME);
在activity中添加接口
implements SensorEventListener
实现接口函数:
@Override public void onSensorChanged(SensorEvent event) { if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){ v_tmp1 = (float)(Math.round(event.values[0]*1000)/1000); v_tmp2 = (float)(Math.round(event.values[1]*1000)/1000); v_tmp3 = (float)(Math.round(event.values[2]*1000)/1000); tv_axu2.setText("ACCELEROMETER:"+v_tmp1+","+v_tmp2+","+v_tmp3); } else if (event.sensor.getType()==Sensor.TYPE_ORIENTATION){ yaw = (float)(Math.round(event.values[0]*1000)/1000); pitch =(~Math.round(event.values[1]*1000))/1000 ; mRoll =(~Math.round(event.values[2]*1000))/1000 ; yaw = (float) (yaw/57.3); pitch = (float) (pitch/57.3); mRoll = (float) (mRoll/57.3); } double cosx,sinx,cosy,siny,cosz,sinz; cosx= Math.cos(mRoll); sinx = Math.sin(mRoll); cosy = Math.cos(pitch); siny = Math.sin(pitch); cosz = Math.cos(yaw); sinz = Math.sin(yaw); double mat0,mat1,mat2,mat3,mat4,mat5,mat6,mat7,mat8; mat0 = cosz * cosy; mat1 = -cosy * sinz; mat2 = siny; mat3 = sinz*cosx + (cosz*sinx * siny); mat4 = cosz*cosx - (sinz*sinx * siny); mat5 = -sinx * cosy; mat6 = (sinz*sinx) - (cosz*cosx * siny); mat7 = (cosz*sinx) + (sinz*cosx * siny); mat8 = cosy * cosx; double X,Y,Z; X = v_tmp1 * mat0 + v_tmp2 * mat3 + v_tmp3 * mat6; Y = v_tmp1 * mat1 + v_tmp2 * mat4 + v_tmp3 * mat7; Z = v_tmp1 * mat2 + v_tmp2 * mat5 + v_tmp3 * mat8; tv_axu1.setText("v->X:"+ X +" v->Y:"+Y +" v->Z:"+Z); }代码中的转换跟变量名比较多,都是为了方便区分跟获取小数点后三位而做的一些处理。大致的意思是:
if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){ v_tmp1 = (float)(Math.round(event.values[0]*1000)/1000); v_tmp2 = (float)(Math.round(event.values[1]*1000)/1000); v_tmp3 = (float)(Math.round(event.values[2]*1000)/1000); tv_axu2.setText("ACCELEROMETER:"+v_tmp1+","+v_tmp2+","+v_tmp3); }判断获取的是手机加速度传感器的值,取值小数点后三位并且转换为float类型。并且在界面上显示出来。
else if (event.sensor.getType()==Sensor.TYPE_ORIENTATION){ yaw = (float)(Math.round(event.values[0]*1000)/1000); pitch =(~Math.round(event.values[1]*1000))/1000 ; mRoll =(~Math.round(event.values[2]*1000))/1000 ; yaw = (float) (yaw/57.3); pitch = (float) (pitch/57.3); mRoll = (float) (mRoll/57.3); }判断获取方向传感器,同样取值小数点后三位并且转化为float类型,pitch与mRoll在这里需要取反,因为下面的算法中需要用到,并且将得到的数值除以57.3,得到弧度制,同样是为了方便算法的运算。
double cosx,sinx,cosy,siny,cosz,sinz; cosx= Math.cos(mRoll); sinx = Math.sin(mRoll); cosy = Math.cos(pitch); siny = Math.sin(pitch); cosz = Math.cos(yaw); sinz = Math.sin(yaw); double mat0,mat1,mat2,mat3,mat4,mat5,mat6,mat7,mat8; mat0 = cosz * cosy; mat1 = -cosy * sinz; mat2 = siny; mat3 = sinz*cosx + (cosz*sinx * siny); mat4 = cosz*cosx - (sinz*sinx * siny); mat5 = -sinx * cosy; mat6 = (sinz*sinx) - (cosz*cosx * siny); mat7 = (cosz*sinx) + (sinz*cosx * siny); mat8 = cosy * cosx; double X,Y,Z; X = v_tmp1 * mat0 + v_tmp2 * mat3 + v_tmp3 * mat6; Y = v_tmp1 * mat1 + v_tmp2 * mat4 + v_tmp3 * mat7; Z = v_tmp1 * mat2 + v_tmp2 * mat5 + v_tmp3 * mat8; tv_axu1.setText("v->X:"+ X +" v->Y:"+Y +" v->Z:"+Z);这一段没什么好说的,就是飞控工程师提供的算法,具体的意义也不需要太理解,算法的人去搞就行。就不在这里浪费时间深入研究了。
同样最后是打印到界面上来
验证方法:图中划线的部分便是打印出来的最终结果,v-X表示是正东方向的加速度。v-y表示的是正北方向的加速度,v-z表示的是水平向上的加速度。当手机平放的时候x与y要接近0,z接近9.8。得出的数据便为正确。但是因为手机的灵敏度问题,数据并不是那么的准确,可以设置变动的数据较大的时候当其为有效。