Android通过手机的传感器计算手机的移动加速度

第一次写博客,非常的担心自己的表达能力不足造成大家的不便,如有不便请谅解,我会继续努力。写出更高质量更好的博客分享。

本人的公司是做无人机的,之前采用手机获取经纬度的数据给飞控进行跟随功能的开发,但是公司觉得还是需要提高无人机跟随的灵敏度,并且希望在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。得出的数据便为正确。但是因为手机的灵敏度问题,数据并不是那么的准确,可以设置变动的数据较大的时候当其为有效。

猜你喜欢

转载自blog.csdn.net/weixin_30267253/article/details/62432598