2014-10-02 75 views
8

我想跟蹤設備只在垂直方向上的移動,即向上和向下移動。這應該與設備的方向無關。的事情,我已經知道或已經嘗試在這些線性加速度方向跟蹤手機的向上和向下移動

  1. 線性加速度由傳感器TYPE_LINEAR_ACCELERATION給出的軸是手機軸,從而跟蹤任何特定軸不有所作爲。

  2. 我試着應用旋轉矢量的轉置或反轉(旋轉矢量的反轉或轉置相同),然後嘗試跟蹤線性加速度矢量的z方向。似乎沒有幫助。

  3. 我想用引力值(TYPE_GRAVITY)做一個點積來獲得加速度的方向,但它似乎很容易出錯。即使當我迅速將設備移動時,它也表示會下降。

我將概述這個方法在這裏

dotProduct = vectorA[0]*vectorB[0]+vectorA[1]*vectorB[1] + vectorA[2]*vectorB[2];  
cosineVal = dotProduct/(|vectorA|*|vectorB|)  
if(cosineVal > 0) down else Up. 

什麼是該方法的缺陷?請幫助,我一直堅持這一段時間。

回答

1

正如我所看到的,在第三種方法中,您試圖找到兩個矢量(重力矢量和加速度矢量)之間角度的cos。這個想法是,如果角度接近於180度,那麼如果角度接近0度,則表示您有向下移動。當角度從-90到90度時,餘弦函數具有正值。所以當你的cosineVal值是正值時,這意味着手機正在下降,即使餘弦值接近1的運動是直線下降。所以反過來也是如此。當餘弦爲負值時(從90度到270度),你有運動。

可能你可以從Sensor.TYPE_ACCELEROMETERhttps://developer.android.com/reference/android/hardware/SensorEvent.html#values載荷那裏你有重力矢量和加速度向量。
我在下面做了一段代碼,你可以試試。

public class MainActivity extends AppCompatActivity implements SensorEventListener { 
    private float[] gravity = new float[3]; 
    private float[] linear_acceleration = new float[3]; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); 
     Sensor mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
     mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 
    } 

    @Override 
    public void onSensorChanged(SensorEvent event) { 
     // alpha is calculated as t/(t + dT) 
     // with t, the low-pass filter's time-constant 
     // and dT, the event delivery rate 

     final float alpha = 0.8f; 

     gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]; 
     gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]; 
     gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]; 

     linear_acceleration[0] = event.values[0] - gravity[0]; 
     linear_acceleration[1] = event.values[1] - gravity[1]; 
     linear_acceleration[2] = event.values[2] - gravity[2]; 

     float scalarProduct = gravity[0] * linear_acceleration[0] + 
       gravity[1] * linear_acceleration[1] + 
       gravity[2] * linear_acceleration[2]; 
     float gravityVectorLength = (float) Math.sqrt(gravity[0] * gravity[0] + 
       gravity[1] * gravity[1] + gravity[2] * gravity[2]); 
     float lianearAccVectorLength = (float) Math.sqrt(linear_acceleration[0] * linear_acceleration[0] + 
       linear_acceleration[1] * linear_acceleration[1] + linear_acceleration[2] * linear_acceleration[2]); 

     float cosVectorAngle = scalarProduct/(gravityVectorLength * lianearAccVectorLength); 

     TextView tv = (TextView) findViewById(R.id.tv); 
     if (lianearAccVectorLength > 2) {//increase to detect only bigger accelerations, decrease to make detection more sensitive but noisy 
      if (cosVectorAngle > 0.5) { 
       tv.setText("Down"); 
      } else if (cosVectorAngle < -0.5) { 
       tv.setText("Up"); 
      } 
     } 
    } 

    @Override 
    public void onAccuracyChanged(Sensor sensor, int i) { 

    } 
}