Compass readings on SGS III

那年仲夏 提交于 2019-11-29 12:36:53

Currently I am investigating compass mechanism on Android and I would recommend to start with low-pass filter in your case. What you need to do - is to apply low-pass filter to both ACCELEROMETER and MAGNETIC_FIELD sensors data. Here is how I implemented that:

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

may be you should clone the value from the sensor reading first and then lowpass the filter if this does not work , I know SONY XPeria phone is very sensitive unlike samsung which is quite stable .

In my view , S3 reading is quite ok under android OS 4.3

event.values.clone;

My recent experience couple data feedback force me to apply rotation vector logic on SONY phone loaded with Invesense sensor and it seemed to be working , although I still do not like the choppy response but I have live with that kind of response on SONY android 4.3 OS . It is also appear to me that any phone loaded invensense sensor need to apply the rotation vector for it to work properly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!