2013-03-25 35 views
0

我正在構建一個Android設備應用程序,它將設備指南針的度數記錄到一個文件中。有兩種方法得到這個學位:Android磁力計返回不平滑數據

方法1:

SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); 
Sensor orientationSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); 
mSensorManager.registerListener(this, orientationSensor, SensorManager.SENSOR_DELAY_NORMAL); 


public void onSensorChanged(SensorEvent event) { 
    float azimuthInDegrees = event.values[0] 
} 

方法2:

SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); 
Sensor accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
Sensor magnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); 
mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL); 
mSensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_NORMAL); 

float[] mGravity; 
float[] mGeomagnetic; 

public void onSensorChanged(SensorEvent event) { 
    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 
     mGravity = event.values.clone(); 
    } 


    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { 
     mGeomagnetic = event.values.clone(); 
    } 

    if (mGravity != null && mGeomagnetic != null) { 
     float R[] = new float[9]; 
     float I[] = new float[9]; 
     boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic); 
     if (success) { 
      float orientation[] = new float[3]; 
     SensorManager.getOrientation(R, orientation); 

     float azimuthInDegress = ((float) Math.toDegrees(orientation[0]) + 360) % 360; 
     } 
    } 
} 

我放置我的設備在北方方向嘗試了兩種方法並順時針旋轉360度,然後再次朝北方向行進。

方法1返回以下記錄的JSON數據:

[ 
    { 
     "start time":"25-03-2013 20:42:11.071", 
     "direction":"N", 
     "end time":"25-03-2013 20:42:14.711" 
    }, 
    { 
     "start time":"25-03-2013 20:42:14.781", 
     "direction":"NE", 
     "end time":"25-03-2013 20:42:18.842" 
    }, 
    { 
     "start time":"25-03-2013 20:42:18.912", 
     "direction":"E", 
     "end time":"25-03-2013 20:42:21.643" 
    }, 
    { 
     "start time":"25-03-2013 20:42:21.712", 
     "direction":"SE", 
     "end time":"25-03-2013 20:42:25.072" 
    }, 
    { 
     "start time":"25-03-2013 20:42:25.142", 
     "direction":"S", 
     "end time":"25-03-2013 20:42:27.524" 
    }, 
    { 
     "start time":"25-03-2013 20:42:27.593", 
     "direction":"SW", 
     "end time":"25-03-2013 20:42:30.113" 
    }, 
    { 
     "start time":"25-03-2013 20:42:30.184", 
     "direction":"W", 
     "end time":"25-03-2013 20:42:32.773" 
    }, 
    { 
     "start time":"25-03-2013 20:42:32.843", 
     "direction":"NW", 
     "end time":"25-03-2013 20:42:34.943" 
    }, 
    { 
     "start time":"25-03-2013 20:42:35.013", 
     "direction":"N", 
     "end time":"25-03-2013 20:42:37.394" 
    } 
] 

方法2個返回記錄以下JSON數據:

[ 
    { 
     "start time":"25-03-2013 20:36:07.337", 
     "direction":"N", 
     "end time":"25-03-2013 20:36:09.728" 
    }, 
    { 
     "start time":"25-03-2013 20:36:09.741", 
     "direction":"NE", 
     "end time":"25-03-2013 20:36:13.832" 
    }, 
    { 
     "start time":"25-03-2013 20:36:13.832", 
     "direction":"E", 
     "end time":"25-03-2013 20:36:16.689" 
    }, 
    { 
     "start time":"25-03-2013 20:36:16.754", 
     "direction":"SE", 
     "end time":"25-03-2013 20:36:16.754" 
    }, 
    { 
     "start time":"25-03-2013 20:36:16.819", 
     "direction":"E", 
     "end time":"25-03-2013 20:36:16.819" 
    }, 
    { 
     "start time":"25-03-2013 20:36:16.819", 
     "direction":"SE", 
     "end time":"25-03-2013 20:36:16.819" 
    }, 
    { 
     "start time":"25-03-2013 20:36:16.884", 
     "direction":"E", 
     "end time":"25-03-2013 20:36:17.014" 
    }, 
    { 
     "start time":"25-03-2013 20:36:17.014", 
     "direction":"SE", 
     "end time":"25-03-2013 20:36:19.546" 
    }, 
    { 
     "start time":"25-03-2013 20:36:19.546", 
     "direction":"S", 
     "end time":"25-03-2013 20:36:22.338" 
    }, 
    { 
     "start time":"25-03-2013 20:36:22.338", 
     "direction":"SW", 
     "end time":"25-03-2013 20:36:25.260" 
    }, 
    { 
     "start time":"25-03-2013 20:36:25.324", 
     "direction":"W", 
     "end time":"25-03-2013 20:36:25.324" 
    }, 
    { 
     "start time":"25-03-2013 20:36:25.324", 
     "direction":"SW", 
     "end time":"25-03-2013 20:36:25.390" 
    }, 
    { 
     "start time":"25-03-2013 20:36:25.390", 
     "direction":"W", 
     "end time":"25-03-2013 20:36:27.987" 
    }, 
    { 
     "start time":"25-03-2013 20:36:28.051", 
     "direction":"NW", 
     "end time":"25-03-2013 20:36:28.128" 
    }, 
    { 
     "start time":"25-03-2013 20:36:28.181", 
     "direction":"W", 
     "end time":"25-03-2013 20:36:28.181" 
    }, 
    { 
     "start time":"25-03-2013 20:36:28.181", 
     "direction":"NW", 
     "end time":"25-03-2013 20:36:28.181" 
    }, 
    { 
     "start time":"25-03-2013 20:36:28.246", 
     "direction":"W", 
     "end time":"25-03-2013 20:36:28.246" 
    }, 
    { 
     "start time":"25-03-2013 20:36:28.246", 
     "direction":"NW", 
     "end time":"25-03-2013 20:36:30.974" 
    }, 
    { 
     "start time":"25-03-2013 20:36:31.038", 
     "direction":"N", 
     "end time":"25-03-2013 20:36:36.233" 
    } 
] 

正如你所看到的,第二種方法的結果並不順利雖然我做了一個從北到北的直道。我更喜歡使用第一種方法,但問題是它已被棄用。另一方面,第二種方法不記錄流暢的數據。我認爲你應該怎麼做?

+0

是設備扁平 – 2013-03-25 20:33:50

+0

@HoanNguyen嗨的一次。是的,它是平坦的。我在兩種方法中都進行了同樣的動作,即將設備平放在手上,並進行360度轉動。 – user1135357 2013-03-25 20:40:24

+0

我嘗試發佈答案,但我可以在電話上鍵入。我會在大約1小時後發佈答案。同時使用TYPE GRAVITY(需要API> 8) – 2013-03-25 21:02:12

回答

2

爲了能夠計算旋轉矩陣,我們假定getRotationMatrix中的重力參數僅爲重力加速度。也就是說,如果(W_1W_2w_3)是世界基礎,W_1是指向EAST一個單位矢量,W_2是指向NORTHw_3的單位矢量朝向指向的單位矢量那麼重力參數被假定爲矢量的標量倍數。
你的結果不平滑的原因是因爲當設備旋轉時,設備的加速度現在包括非重力加速度。現在加速計值不再準確地接近重力。因此,這個詞的基礎並不準確。該getOrientation方法計算由正交投影設備單元y軸W_1方位角,W_2平面(東 - 北平面),然後計算所得到的矢量和W_2(北)之間的角度向量。所以,如果w_1,w_2,沒有準確表示,那麼您的結果將不會被記錄下來。
爲了提高精確度,您需要過濾加速度計以消除引力以外的其他加速度。爲此,最簡單的方法是低通濾波器。
對於API> 8,android提供了TYPE_GRAVITY,我可以肯定它只是濾波的加速度計值,濾波方法可能是某種KALMAN濾波器。使用TYPE_GRAVITY可將結果與低通濾波器相提高10度。
此外,爲了消除波動,保留結果的歷史並對其進行平均。您可以將旋轉矩陣保存在列表中,然後平均或保存方位角,然後取平均值。由於其週期性,平均方位角必須小心。您可以使用以下方法對它們進行平均。

public static final float averageAngle(float[] terms, int totalTerm) 
{ 
    float sumSin = 0; 
    float sumCos = 0; 
    for (int i = 0; i < totalTerm; i++) 
    { 
     sumSin += Math.sin(terms[i]); 
     sumCos += Math.cos(terms[i]); 
    } 
    return (float) Math.atan2(sumSin/totalTerm, sumCos/totalTerm); 
} 

注:我想原因TYPE_ORIENTATION被貶值,因爲它僅提供了通常意義上的方向只有當設備是平的或接近平。它通過getOrientation返回結果。現在,如果該設備是垂直並旋轉,用於POTRAIT和橫向之間例如一半,然後返回getRotation方位角爲其中y軸的投影到W_1W_2平面指向的方向。這不是後攝像機指向的方向,這是-z軸的方向。人們不理解這一點,並在所有情況下使用,因此android折舊。如果你仍然在使用它,你會感到驚訝,因爲手機制造商以不同的方式實施它。宏達電和摩托羅拉將給你完全不同的結果。
你可以在Convert magnetic field X, Y, Z values from device into global reference frame得到我的答案的詳細信息,並在Magnetic Fields, Rotation Matrix And global coordinates