android - 检测向下加速度,特别是电梯

android - detect downward acceleration, specifically an elevator

我希望能够检测到 phone 对地面有加速度的情况(可能意味着重力传感器也必须在这里使用)。

我在 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 轴上的加速度。

这一切都很好,但问题显然在于,这取决于用户如何握住 phone,例如,在电梯中 - 如果他将它平放,与地面平行 - Z axis 会改变,如果他把它举直 - Y axis 会改变,等等

因此,例如,如果用户对角握住 phone,加速度将在不同的轴之间“分配”,并且考虑重力方向的某种数学工作将是需要计算该方向的实际加速度。

如果我错了请纠正我?

有没有可靠的方法来检测向下(朝向地球)的加速度?也许使用陀螺仪等其他传感器?

顺便说一句,关于TYPE_LINEAR_ACCELERATION类型,我看了这个answer,说其实不太准确。

使用一些基础物理学。加速度是一个矢量。矢量 v 的大小始终等于 (v.v)^.5,或点积的平方根。或者更简单地说 (x^2+y^2+z^2)^.5。这会告诉你加速度的大小,但不会告诉你它是朝向地球还是远离地球。

如果您需要知道它是朝向地球还是远离地球,您可以将其与来自 SensorManager.getOrientation 的数据结合起来。不过,您可能需要在他们进入电梯之前执行此操作 - 方向代码使用重力作为其输入之一,因此如果您尝试在电梯中使用它,它可能会搞砸。你需要测试一下。

如果您需要将其分解为地球 x、y 和 z 轴的加速度 - 简单几何。从方向结果中获取角度,并使用三角属性转换轴。如果您不知道这些公式,您需要稍微阅读一下三角函数,否则即使我告诉您,您也会弄错。

我还想测量垂直运动。我就是这样做的,它对我有用。第一次在这个网站上发帖,我不知道如何正确格式化。

使用两个不同的 android 传感器:Type_linear_Acceleration and Type_Gravity

线性加速度会给你在 phone 的 X、Y 和 Z 轴上的加速度,Gravity 也会这样做,但只是针对重力。您知道重力值的总和应该 = 9.8,但这将根据 phone 方向在 X、Y 和 Z 坐标之间进行拆分。

我不会过多地讨论它的数学问题,但以下内容将为您提供无重力的垂直加速度。如果你想通过一些值更多地理解它 运行 就好像 phone 是垂直的,然后水平的,即使 phone 是倾斜的。

vertical acceleration = (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);

}