[android]罗盘读数 SGS 第三

发布时间: 2014/8/29 23:11:27
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

我的应用程序需要显示当前轴承的使用及其指南针的设备。代码我使用 (见下文) 作品非常好我的 Galaxy Nexus 和银河一,但是指南针上三星 Galaxy S III 疯狂地旋转周围。我试过做图 8 重新校准装置,但那不能改变任何东西。奇怪的是其他指南针的应用程序下载从谷歌戏剧工作 SIII 就很好。这里的问题是什么?

float[] mGravity;
float[] mGeomagnetic;

public void onSensorChanged( SensorEvent event ) {
    float azimuth = 0f;
    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        mGravity = event.values;
    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
        mGeomagnetic = event.values;
    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);
            azimuth = orientation[0]; // orientation contains: azimut, pitch and roll
        }
     }

    //Discard 0.0-values
    if(azimuth == 0.0) { return; }

    //Convert the sensor value to degrees
    azimuth = (float) Math.toDegrees(azimuth); //same as azimuth = -azimuth*360/(2*3.14159f);


    //Smooth the sensor-output
    azimuth = smoothValues(azimuth);
}

//From http://stackoverflow.com/questions/4699417/android-compass-orientation-on-unreliable-low-pass-filter
//SmoothFactorCompass: The easing float that defines how smooth the movement will be (1 is no smoothing and 0 is never updating, my default is 0.5).
//SmoothThresholdCompass: The threshold in which the distance is big enough to turn immediately (0 is jump always, 360 is never jumping, my default is 30).
static final float SmoothFactorCompass = 0.5f;
static final float SmoothThresholdCompass = 30.0f;
float oldCompass = 0.0f;
private float smoothValues (float newCompass){
    if (Math.abs(newCompass - oldCompass) < 180) {
        if (Math.abs(newCompass - oldCompass) > SmoothThresholdCompass) {
            oldCompass = newCompass;
        }
        else {
            oldCompass = oldCompass + SmoothFactorCompass * (newCompass - oldCompass);
        }
    }
    else {
        if (360.0 - Math.abs(newCompass - oldCompass) > SmoothThresholdCompass) {
            oldCompass = newCompass;
        }
        else {
            if (oldCompass > newCompass) {
                oldCompass = (oldCompass + SmoothFactorCompass * ((360 + newCompass - oldCompass) % 360) + 360) % 360;
            } 
            else {
                oldCompass = (oldCompass - SmoothFactorCompass * ((360 - newCompass + oldCompass) % 360) + 360) % 360;
            }
        }
    }
    return oldCompass;
}

解决方法 1:

目前我正在调查罗盘机制上 Android ,我会建议开始与低通的 filter 你的情况。你需要做的事-是要应用低通 filter 对加速度计和 MAGNETIC_FIELD 传感器数据。这里是如何实现的:

private float[] accel;
private float[] geomagnetic;
float R[] = new float[9];
float I[] = new float[9];
float orientation[] = new float[3];

@Override
public void onSensorChanged(SensorEvent event)
{
    synchronized (this)
    {
        float azimuth = -1f;

        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
            accel = lowPass( event.values.clone(), accel );

        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
            geomagnetic = lowPass(event.values.clone(), geomagnetic);

        if (accel != null && geomagnetic != null)
        {

            boolean success = SensorManager.getRotationMatrix(R, I,
                    accel, geomagnetic);

            SensorManager.remapCoordinateSystem(R,
                    SensorManager.AXIS_X, SensorManager.AXIS_Z, R);

            if (success)
            {
                SensorManager.getOrientation(R, orientation);
                azimuth = orientation[0]; // orientation contains:
                                         // azimuth, pitch
                                         // and roll
                float newHeading = azimuth * 360 / (2 * 3.14159f);

                //do what you need to do with new heading
            } 
        }
    }
}


/*
 * time smoothing constant for low-pass filter 0 ≤ alpha ≤ 1 ; a smaller
 * value basically means more smoothing See:
 * http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization
 */
static final float ALPHA = 0.15f;

/**
 * @see http
 *      ://en.wikipedia.org/wiki/Low-pass_filter#Algorithmic_implementation
 * @see http
 *      ://developer.android.com/reference/android/hardware/SensorEvent.html
 *      #values
 */

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;
}
赞助商