安卓——检测向下加速度,尤其是电梯

3
我希望能够检测到手机朝地面加速的情况(这可能意味着需要使用重力传感器)。我已经在Android文档中阅读了很多关于这个主题的内容,包括高通和低通滤波器以及其他帖子,现在我有一个代码示例,可以剥离重力后获取X,Y和Z轴上的加速度。
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

        final float alpha = (float) 0.8;

        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];  
}

所以,linear_acceleration 应该是不带重力的 X、Y、Z 轴加速度。这很好,但问题显然在于它取决于用户如何拿着手机,例如在电梯里 - 如果他将其平放,与地面平行 - Z 轴 将改变,如果他将其竖直拿起 - Y 轴 将改变等等。因此,例如,如果用户斜向持有手机,则加速度将在不同轴之间“分配”,需要进行某种数学计算,考虑重力方向在哪里,才能计算出实际方向上的加速度。如果我理解有误,请纠正我。有没有可靠的方法来检测向下(朝向地球)的加速度?也许可以使用其他传感器,比如陀螺仪?顺便说一下 - 关于 TYPE_LINEAR_ACCELERATION 类型,我读到了这个答案,说它实际上并不是很准确。

你能使用变化最大的轴值吗? - tallpaul
2个回答

1
使用一些基本物理学。加速度是一个向量。向量v的大小总是等于(v.v)^ .5,或点积的平方根。或者用更简单的术语表示为(x ^ 2 + y ^ 2 + z ^ 2)^ .5。这将告诉您加速度的大小,但不知道它是朝向地球还是远离地球。
如果您需要知道它是朝向地球还是远离地球-您可以将其与SensorManager.getOrientation的数据结合使用。不过,您可能需要在他们进入电梯之前这样做-定位代码使用重力作为其输入之一,因此如果您尝试在电梯中使用它,则可能会出现问题。您需要测试一下。
如果您需要将其分解为地球x,y和z轴上的加速度-简单的几何。从定位结果中取得角度,并使用三角函数属性转换轴。如果您不知道所需的公式,您需要稍微阅读一下三角函数,否则即使我告诉您这些公式,您也会弄错它们。

1
谢谢你的回答。我成功地使用了你的公式得到了总加速度,而且我也得到了方向的俯仰角、翻滚角和方位角 - 但是我真的不确定如何从这里继续并得到朝向地球的加速度。 - Ofek Agmon
你能分享公式吗? - Barel elbaz

1
我也希望能够测量垂直运动。这是我做的,对我有效。第一次在此网站发布文章,我不知道如何正确格式化。
使用两种不同的Android传感器:Type_linear_Acceleration和Type_Gravity
线性加速度将给出手机X、Y和Z轴的加速度,而重力将执行相同的操作,但仅适用于重力。您知道重力值的总和应该= 9.8,但这将根据手机方向在X、Y和Z坐标之间分配。
我不会过多地介绍数学问题,但以下内容将为您提供没有重力的垂直加速度。如果您想更好地理解它,请运行一些值,就好像手机是垂直或水平保持,即使手机是倾斜的也有效。

垂直加速度=(LinearAccelX * GravityX / 9.8)+(LinearAccelY * GravityY / 9.8)+(LinearAccelZ * GravityZ / 9.8)。

请参见下面的代码(已删除不相关部分)。
{public class MainActivity extends AppCompatActivity implements SensorEventListener {

SensorManager sm;
Sensor linearaccelerometer;
Sensor gravity;
double Yaccel;
double Xaccel;
double Zaccel;
double gravityY;
double gravityX;
double gravityZ;
double verticalAccel;

    sm = (SensorManager) getSystemService(SENSOR_SERVICE);
    linearaccelerometer = sm.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
    gravity = sm.getDefaultSensor(Sensor.TYPE_GRAVITY);

    sm.registerListener(this, linearaccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
    sm.registerListener(this, gravity, SensorManager.SENSOR_DELAY_NORMAL);
}

public void onSensorChanged(SensorEvent event) {

    Sensor sensor = event.sensor;

    if (sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {
        Xaccel = (double) event.values[0];
        Yaccel = (double) event.values[1];
        Zaccel = (double) event.values[2];
    }

    if (sensor.getType() == Sensor.TYPE_GRAVITY) {
        gravityX = (double) event.values[0];
        gravityY = (double) event.values[1];
        gravityZ = (double) event.values[2];
    }

    verticalAccel = (Xaccel * gravityX / 9.8) + (Yaccel * gravityY / 9.8) +  (Zaccel *gravityZ /9.8);

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接