Android - 如何检测指南针度数的变化(Java)



我有以下代码可以完美地适用于我的Nexus 5。

public void onSensorChanged(SensorEvent event) {
        float degree = Math.round(event.values[0]);
        displayMsg.setText(String.valueOf(degree));
}

degree包含指南针的方向。我想做的是检测方向的变化。因此,假设一个人向北走,然后向右转10度。一旦这个人改变方向,我希望能够注意到。此外,也存在不确定性。例如,当人向北行走时,方向不是恒定的 0 度。它将在 358 度和 2-3 度之间波动。

我想用Timer.schedule每 500 毫秒存储一次度数,然后做一个

if(Math.abs(degree - storedDegree) > 10)
   Toast.makeText(this,"Direction Changed",Toast.LENGTH_SHORT).show();

但是,我认为由于创建的线程数量,此方法会耗尽内存。有没有更智能/更好的方法来检测方向变化?


更新

这是我正在做的完整代码。

我正在计算步数,我想保持步数的方向。 一旦方向改变 10 度,计步器应该存储它的值(比如在数组列表中(,然后转到 0 并重新开始计数。

boolean start = true;
@Override
public void onSensorChanged(SensorEvent event) {
    //------------------------------Compass--------------------------------------
    final float degree = Math.round(event.values[0]);
    displayMsg.setText(String.valueOf(degree));
    //---------------------------------------------------------------------------
    Sensor sensor = event.sensor;
    float[] values = event.values;
    int value = -1;
    int steps;
    if (values.length > 0) {
        value = (int) values[0];
    }
    if(mode.equals("Start"))
    {
        if (sensor.getType() == Sensor.TYPE_STEP_COUNTER) 
        {
            if(start)
            {
                count = value;
                start = false;
            }
            steps = value-count;
            stepCounter.setText("Step Counter Detected : " + steps);
        } 
    }
}

我会使用低通滤波器来消除波动。

代码如下:

protected float[] lowPass(float[] input, float[] output) {
    if (output == null) return input;
    for (int i = 0; i < input.length; i++) {
        output[i] = output[i] + ALPHA * (input[i] - output[i]);
    }
    return output;
}

阿尔法在哪里静态最终浮点数 ALPHA = 0.25f;

我还将发布用于获取"方向"的代码。也许它可以帮助您:

protected void onResume() {
    super.onResume();
    mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
    mSensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_UI);
}
protected void onPause() {
    super.onPause();
    mSensorManager.unregisterListener(this);
}

@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        mGravity = lowPass(event.values.clone(), mGravity);
    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
        mGeomagnetic = lowPass(event.values.clone(), mGeomagnetic);
    if (mGravity != null && mGeomagnetic != null) {
        float R[] = new float[9];
        float I[] = new float[9];
        boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
        if (success) {
            float orientation[] = new float[3];
            SensorManager.getOrientation(R, orientation);
            azimut = orientation[0]; // orientation contains: azimut, pitch and roll
        }
    }
}

在此之后,像这样使用方位角:

        if (azimut != null) {
            canvas.rotate(-azimut * 360 / (2 * 3.14159f), centerx, centery);
            if ((azimut > -0.2) && (azimut < 0.2)) current_direction = "North";
            if ((azimut > 1.3) && (azimut < 1.7)) current_direction = "East";
            if (((azimut < -2.8) && (azimut > -3.2)) || ((azimut < 3.2) && (azimut > 2.8))) current_direction = "South";
            if ((azimut > -1.7) && (azimut < -1.3)) current_direction = "West";
        }

我认为您的问题与传感器有关,而不是您的逻辑。你可以试试这个,但我并没有真正失败传感器。 我知道定位服务可以为您提供设备轴承(通过GPS(,这也是一种选择。

您能否检查当前度数的变化是否超过阈值,然后使用新度数更新存储值?

一个可能的例子是这样的:这个想法是,由于每当更新值时都会调用onSensorChanged,因此您可以检查当前度数和存储值之间的差异是否超过某个阈值。如果是采取行动并存储新学位,则直接忽略更改。

private float storedDegree;
public void onSensorChanged(SensorEvent event) {
    if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
        float degree = Math.round(event.values[0]);
        if(Math.abs(degree - storedDegree) > 10) {
            Toast.makeText(this,"Direction Changed",Toast.LENGTH_SHORT).show();
            displayMsg.setText(String.valueOf(degree));
            storedDegree = degree;
        }
    }
}

最新更新