Compass readings on SGS III

后端 未结 2 522
孤独总比滥情好
孤独总比滥情好 2020-12-20 06:14

My app needs to show the current bearing of the device using its compass. The code I\'m using (below) works perfectly fine on my Galaxy Nexus and Galaxy One, but the compass

2条回答
  •  时光说笑
    2020-12-20 06:44

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

提交回复
热议问题