1. 程式人生 > >Pro Android學習筆記(一五五) 感測器(5) 磁場感測器和方位(上)

Pro Android學習筆記(一五五) 感測器(5) 磁場感測器和方位(上)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

文章轉載只能用於非商業性質,且不能帶有虛擬貨幣、積分、註冊等附加條件。轉載須註明出處http://blog.csdn.net/flowingflying/以及作者@愷風Wei

磁場感測器(Magnetic Field Sensors)

磁場感測器可以用來檢測磁場大小,和加速度感測器一樣,有x、y、z軸三個方向,單位為uT(microteslas)。磁場感測器也稱為compass(指南針),在uses-feature中使用android.hardware.sensor.compass作為其名字。說實在的,單看磁場數值也看不出所以然。

說個故事,單位部門調整,一撥同事到10樓,這是上下移動實驗室的夾層,下面是行動網路(有4G小基站)實驗室。一聽要挪過去,各個憂心忡忡,這輻射如何辦?按祕書的說法,怎麼辦,涼拌。正好玩磁場感測器,雖然magnetic不是electromagnetic,電場、磁場相互作用,在具體的都還給老師了。手頭上也沒有什麼能夠進行測試的,就用磁場感測器測一測。這種事情多半都是自己嚇自己,智慧手機將成為摸金校尉的必備工具。

下面是小例子程式碼片段:

public class MagneticFieldSensorActivity extends Activity implements SensorEventListener{
    ......
   @Override
    protected void onCreate(Bundle savedInstanceState) {
        ......
        sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);       
    }

    ...... //註冊和登出磁場感測器監聽器



    private int count = 1;
    @Override
    public void onSensorChanged(SensorEvent event) {
        if( count++ == 20){ //磁場感測器很敏感,每20個變化,顯示一次數值
            double value = Math.sqrt(event.values[0]*event.values[0] + event.values[1]*event.values[1]
                    +event.values[2]*event.values[2]);
            String str = String.format("X:%8.4f , Y:%8.4f , Z:%8.4f \n總值為:%8.4f",
                    event.values[0],event.values[1],event.values[2],value);             
            count = 1;
            tv.setText(str);
        }           
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Nothing here   
    }
    
}

方位感測器(Orientation Sensors)

磁場感測器和加速度感測器結合可或者裝置擺放角度,兩者結合可以獲取方位。這些計算由Android代勞了,SensorManager提供getRotationMatrix(),獲得轉動的矩陣,並進一步通過getOrientation()獲得方位矩陣。Android還有方位感測器(orientation Sensors),不是物理實體,而是通過acceleration感測器和磁場感應器來獲取方位,而在Android2.2開始方位感測器就被deprecated

裝置擺放情況通過azimuth、pitch和roll來表示。

azimuth即方位角,就是手機方向和正北的夾角,百度百科這樣描述方位角:是從某點的指北方向線起,依順時針方向到目標方向線之間的水平夾角。pitch和roll可能是引用了航天的術語。azimuth,pitch和roll分別是z軸、X軸和Y軸的旋轉角度。

老方法採用orientation感測器,azimuth從0~360。pitch是在x軸方向的轉動角度,其實就是Y軸和水平面的仰角,範圍為-180~180,正的為朝下(手機頭低於水平面),負的為朝上,pitch的方向逆時針為正。roll是Y軸防線的轉動角度,實際就是X軸和水平面的角度,範圍在-90~90,同樣逆時針為正,右軸高於左軸時為正,右軸高於左軸時為負。

新的方法,azimuth的範圍是-180~180,當然我們可以進行適當的處理,如果小於零,則加360,這樣就可以和orientation的得到的值一樣。需要注意的是pitch的範圍是-90~90,機頭上翹為負;roll的範圍是-180~180,和老方法相反,右軸高時為負。

這兩種方式的數值可能會使人有些迷糊,我們在使用之前先查文件弄清楚就是了。我曾經有個疑惑為何有兩個數值的範圍是360度,其中一個數值只有180度。想想球面就知道了,以地球儀為例,經度範圍是360°,維度範圍是180°,就可以確定球面上的任何一點,以球心到該點假設是手機中軸線,還有一個圍繞Y軸360°轉的角度的第三維,這就可以確定所有的排放方式。

小例子

下面小例子我們將同時展現新舊兩種方式。

public class VirtualJax extends Activity implements SensorEventListener{
    ... ... //註冊和登出感測器監聽器,本例涉及三個感測器(加速度感測器、地磁感測器和方位感測器),可以用sensorManager.unregister(this)登出監聽器所涉及的全部感測器
  
    private Sensor accelSensor = null, compassSensor = null, orientSensor = null;
    private float[] accelValues = new float[3], compassValues = new float[3],orientValues = new float[3];
    private boolean ready = false;
//檢查感測器是否正常工作,即是否同時具有加速感測器和磁場感測器。 
    private float[] inR = new float[9];
    private float[] inclineMatrix = new float[9];
    private float[] prefValues = new float[3];
    private double mInclination;
    private int count = 1;

   
    @SuppressWarnings("deprecation") //因為orientaion已經不再使用,為了不要顯示warning,加上此標識
    @Override
    public void onSensorChanged(SensorEvent event) {
        //【1】將相關感測器的數值分別讀入accelValues,compassValues(磁力感應器的數值)和orientValues陣列中
        switch(event.sensor.getType()){
        case Sensor.TYPE_ACCELEROMETER:
            for(int i = 0 ; i < 3 ; i ++){
                accelValues[i] = event.values[i];
            }
            if(compassValues[0] != 0) //如果accelerator和magnetic感測器都有數值,設定為真 
                ready = true;
            break;
           
        case Sensor.TYPE_MAGNETIC_FIELD:
            for(int i = 0 ; i < 3 ; i ++){
                compassValues[i] = event.values[i];
            }
            if(accelValues[2] != 0) //檢查accelerator和magnetic感測器都有數值,只是換一個軸向檢查
                ready = true;
            break;
           
        case Sensor.TYPE_ORIENTATION:
            for(int i = 0 ; i < 3 ; i ++){
                orientValues[i] = event.values[i];
            }
            break;
        }
       
        if(!ready)
            return;
   
      //【2】根據加速感測器的數值accelValues[3]和磁力感應器的數值compassValues[3],進行矩陣計算,獲得方位
        //【2.1】計算rotation matrix R(inR)和inclination matrix I(inclineMatrix) 
        if(SensorManager.getRotationMatrix(inR, inclineMatrix, accelValues, compassValues)){
            /* 【2.2】根據rotation matrix計算裝置的方位。,範圍陣列:
            values[0]: azimuth, rotation around the Z axis.
            values[1]: pitch, rotation around the X axis.
            values[2]: roll, rotation around the Y axis.*/

           SensorManager.getOrientation(inR, prefValues);
           //【2.2】根據inclination matrix計算磁仰角,地球表面任一點的地磁場總強度的向量方向與水平面的夾角。
             mInclination = SensorManager.getInclination(inclineMatrix);
           
           //【3】顯示測量值
            if(count++ % 100 == 0){
                doUpdate(null);
                count = 1;
            }
           
        }else{
            Toast.makeText(this, "無法獲得矩陣(SensorManager.getRotationMatrix)", Toast.LENGTH_LONG);
            finish();
        }

       
    }

   //【3】顯示測量值
    public void doUpdate(View v){
        if(!ready)
            return;
        //preValues[0]是方位角,單位是弧度,範圍是-pi到pi,通過Math.toDegrees()轉換為角度
        float mAzimuth = (float)Math.toDegrees(prefValues[0]); 
        /*//糾正為orientation的數值。
         * if(mAzimuth < 0)
            mAzimuth += 360.0;*/

       
        String msg = String.format("推薦方式:\n方位角:%7.3f\npitch: %7.3f\nroll: %7.3f\n地磁仰角:%7.3f\n",
                mAzimuth,Math.toDegrees(prefValues[1]),Math.toDegrees(prefValues[2]),
                Math.toDegrees(mInclination));
        nowOne.setText(msg);
       
        msg = String.format("老方式:\n方位角:%7.3f\npitch: %7.3f\nroll: %7.3f",
                orientValues[0],orientValues[1],orientValues[2]);
        oldOne.setText(msg);         
    }   
   
}

執行結果如下:

相關小例子程式碼: Pro Android學習:感測器小例子

相關連結:我的Android開發相關文章

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述