我正在尝试使用Android设备上的加速计(Sensor.TYPE_LINEAR_ACCELERATION
)计算位移。这是我的OnSensorChanged()
方法:
public void onSensorChanged(SensorEvent event) {
accelX = event.values[0];
accelY = event.values[1];
accelZ = event.values[2];
long currentTime = System.currentTimeMillis() / 1000;
if(prevTime == 0) prevTime = currentTime;
long interval = currentTime - prevTime;
prevTime = currentTime;
velX += accelX * interval;
velY += accelY * interval;
velZ += accelZ * interval;
distX += prevVelX + velX * interval;
distY += prevVelY + velY * interval;
distZ += prevVelZ + velZ * interval;
prevAccelX = accelX;
prevAccelY = accelY;
prevAccelZ = accelZ;
prevVelX = velX;
prevVelY = velY;
prevVelZ = velZ;
}
然而,在任何移动后,Velocity都不会返回0。除非非常突然,否则减速效果不大。这导致一些非常不准确的距离值。
加速度计也非常嘈杂,所以我补充说:
accelX = (accelX * accelKFactor) + prevAccelX * (1 - accelKFactor);
accelY = (accelY * accelKFactor) + prevAccelY * (1 - accelKFactor);
accelY = (accelX * accelKFactor) + prevAccelY * (1 - accelKFactor);
accelKFactor
= .01
我错过了一些明显的东西吗?
我的最终目标只是能够判断设备是否移动了超过10英尺,但是现在,我的数据几乎没用。
编辑:
我发现了部分问题。 currentTime
很长,但我将系统时间以ms为单位除以1000得到秒。所以速度只能真正更新每1秒。将currentTime
更改为双倍会有所帮助,但并不能完全解决问题。
答案 0 :(得分:0)
SensorEvent有一个时间戳字段,以纳秒为单位。使用它而不是System.currentTimeMillis()。以下是文档中的示例:
private static final float NS2S = 1.0f / 1000000000.0f;
private float timestamp;
public void onSensorChanged(SensorEvent event) {
// This timestep's delta rotation to be multiplied by the current rotation
// after computing it from the gyro sample data.
if (timestamp != 0) {
final float dT = (event.timestamp - timestamp) * NS2S;
通过这种方式跟踪位移对初始条件非常敏感,因此这应该有所帮助。
另外,您可能会更好地使用Location.getSpeed()。如果您无法获得信号,请考虑仅将加速度计用作备份。
答案 1 :(得分:0)
请检查下面的代码
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
float appliedAcceleration = 0;
float currentAcceleration = 0;
float velocity = 0;
Date lastUpdatedate;
double calibration = Double.NaN;
@Override
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
lastUpdatedate = new Date(System.currentTimeMillis());
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}
@Override
public void onSensorChanged(SensorEvent event) {
double x = event.values[0];
double y = event.values[1];
double z = event.values[2];
double a = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
if (calibration == Double.NaN)
calibration = a;
else {
Date timeNow = new Date(System.currentTimeMillis());
long timeDelta = timeNow.getTime()-lastUpdatedate.getTime();
lastUpdatedate.setTime(timeNow.getTime());
float deltaVelocity = appliedAcceleration * (timeDelta/1000);
appliedAcceleration = currentAcceleration;
velocity += deltaVelocity;
final double mph = (Math.round(100*velocity / 1.6 * 3.6))/100;
Log.i("SensorTestActivity","SPEEDDDDD=== "+mph+" "+velocity);
currentAcceleration = (float)a;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
protected void onStart() {
super.onStart();
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onStop() {
super.onStop();
sensorManager.unregisterListener(this);
}
}