我试图仅在垂直方向上跟踪设备的移动,即向上和向下移动.这应该与设备的方向无关.我已经知道或尝试过的事情就是这些
>线性加速度由传感器TYPE_LINEAR_ACCELERATION给出,轴是电话轴,因此跟踪任何特定轴都没有区别.
>我尝试应用转置或旋转矢量的倒数(旋转矢量的反转或转置相同),然后尝试跟踪线性加速度矢量的z方向.似乎没有帮助.
>我正在尝试使用重力值(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.
这种方法有什么缺陷?请帮助,我已经坚持了一段时间了.
解决方法@H_502_14@
在我看来,在第3种方法中,你试图找到两个矢量之间的角度cos(重力矢量和加速度矢量).并且想法是如果角度接近180度你有向上运动,如果角度接近0度你有向下运动.余弦是角度为-90到90度时具有正值的函数.因此,当你的cosineVal值为正时,这意味着手机正在下降,即使cosineVal接近1运动也是直线下降.所以反之亦然.当余弦为负时(从90度到270度),你就有了运动.
也许你可以从https://developer.android.com/reference/android/hardware/SensorEvent.html#values获得Sensor.TYPE_ACCELEROMETER的矢量,你有重力矢量和加速度矢量.
我在下面制作了一个代码片段,你可以试试.
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) {
}
}
也许你可以从https://developer.android.com/reference/android/hardware/SensorEvent.html#values获得Sensor.TYPE_ACCELEROMETER的矢量,你有重力矢量和加速度矢量.
我在下面制作了一个代码片段,你可以试试.
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) { } }