在SGS III罗盘读数 [英] Compass readings on SGS III

查看:134
本文介绍了在SGS III罗盘读数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序需要显示使用其指南针设备的当前方位。在code我使用(下)工作完全正常在我的Galaxy Nexus的和银河之一,但指南针的是,三星Galaxy S III转圈疯狂。我试着做8字形重新校准设备,但是这不会改变任何东西。奇怪的是,从谷歌下载其他应用程序指南针播放只是罚款的SIII。可能是什么问题在这里?

 浮法[] mGravity;
浮动[] mGeomagnetic;

公共无效onSensorChanged(SensorEvent事件){
    浮方位= 0F;
    如果(event.sensor.getType()== Sensor.TYPE_ACCELEROMETER)
        mGravity = event.values​​;
    如果(event.sensor.getType()== Sensor.TYPE_MAGNETIC_FIELD)
        mGeomagnetic = event.values​​;
    如果(mGravity = NULL和放大器;!&安培;!mGeomagnetic = NULL){
        浮动 -  [R [] =新的浮动[9];
        浮动我[] =新的浮动[9];
        布尔成功= SensorManager.getRotationMatrix(R,I,mGravity,mGeomagnetic);
        如果(成功){
            浮方位[] =新的浮动[3];
            SensorManager.getOrientation(R,取向);
            方位角=取向[0]; //方向包括:方位角,俯仰和横滚
        }
     }

    //丢弃0.0值
    如果(方位== 0.0){返回; }

    //将传感器值度
    方位角=(浮点)Math.toDegrees(方位); //相同方位角=  - 方位* 360 /(2 * 3.14159f);


    //平滑传感器输出
    方位角= smoothValues​​(方位);
}

//从http://stackoverflow.com/questions/4699417/android-compass-orientation-on-unreliable-low-pass-filter
// SmoothFactorCompass:在宽松的浮动,定义了如何平滑的运动将是(1为不平滑和0永不更新,我的默认值为0.5)。
// SmoothThresholdCompass:在距离足够大时,立即将阈值(0跳一如既往,360永远不会跳,我默认为30)。
静态最终浮动SmoothFactorCompass = 0.5F;
静态最终浮动SmoothThresholdCompass = 30.0f;
浮oldCompass = 0.0;
私人浮动smoothValues​​(浮动newCompass){
    如果(Math.abs(newCompass  -  oldCompass)< 180){
        如果(Math.abs(newCompass  -  oldCompass)> SmoothThresholdCompass){
            oldCompass = newCompass;
        }
        其他 {
            oldCompass = oldCompass + SmoothFactorCompass *(newCompass  -  oldCompass);
        }
    }
    其他 {
        如果(360.0  -  Math.abs(newCompass  -  oldCompass)> SmoothThresholdCompass){
            oldCompass = newCompass;
        }
        其他 {
            如果(oldCompass> newCompass){
                oldCompass =(oldCompass + SmoothFactorCompass *((360 + newCompass  -  oldCompass)%360)+ 360)%360;
            }
            其他 {
                oldCompass =(oldCompass  -  SmoothFactorCompass *((360  -  newCompass + oldCompass)%360)+ 360)%360;
            }
        }
    }
    返回oldCompass;
}
 

解决方案

目前我正在研究在Android上的指南针机制,我建议先从你的情况低通滤波器。 你需要做的 - 是采用低通滤波这两个加速计和MAGNETIC_FIELD传感器的数据。 下面是我是如何实现的:

 私人浮法[]加速;
私人浮法[]地磁;
浮动 -  [R [] =新的浮动[9];
浮动我[] =新的浮动[9];
浮方位[] =新的浮动[3];

@覆盖
公共无效onSensorChanged(SensorEvent事件)
{
    同步(这)
    {
        浮方位= -1f;

        如果(event.sensor.getType()== Sensor.TYPE_ACCELEROMETER)
            加速=低通(event.values​​.clone(),加速度);

        如果(event.sensor.getType()== Sensor.TYPE_MAGNETIC_FIELD)
            地磁=低通(event.values​​.clone(),地磁);

        如果(加速= NULL和放大器;!&安培;!地磁= NULL)
        {

            布尔成功= SensorManager.getRotationMatrix(R,I,
                    加速,地磁);

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

            如果(成功)
            {
                SensorManager.getOrientation(R,取向);
                方位角=取向[0]; //方向包括:
                                         //方位角,俯仰
                                         //和轧辊
                浮newHeading =方位角* 360 /(2 * 3.14159f);

                //做你需要做新的标题
            }
        }
    }
}


/ *
 *时间平滑常数的低通滤波器0≤阿尔法≤1;较小
 *值基本上意味着更平滑参见:
 * http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization
 * /
静态最终浮动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
 * /

保护浮法[]低通(浮法[]输入,浮法[]输出)
{
    如果(输出== NULL)
        返回输入;

    的for(int i = 0; I< input.length;我++)
    {
        输出[I] =输出[I] + ALPHA *(输入[I]  - 输出[I]);
    }
    返回输出;
}
 

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 is spinning around wildly on a Samsung Galaxy S III. I've tried doing a figure-8 to recalibrate the device, but that doesn't change anything. The weird thing is that other compass apps downloaded from Google Play work just fine on the SIII. What could be the issue here?

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

解决方案

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

这篇关于在SGS III罗盘读数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆