【问题标题】:Not getting direction from sensors in landscape mode or after flipping orientation在横向模式下或翻转方向后无法从传感器获取方向
【发布时间】:2012-08-28 21:23:41
【问题描述】:

我正在尝试在 Android 中获取相机的方向。我的代码在纵向上运行良好(我通过慢慢转一圈并以 1 秒的间隔查看更新来测试它),但它在横向上根本不起作用——数字似乎是随机变化的。从纵向切换到横向后,它也完全失控。这是我的代码

public void onSensorChanged(SensorEvent event) {

    switch (event.sensor.getType()) {
    case Sensor.TYPE_ACCELEROMETER:
        accelerometerValues = event.values.clone();

        break;
    case Sensor.TYPE_MAGNETIC_FIELD:
        geomagneticMatrix = event.values.clone();
        break;
    default:
        break;
    }   

    if (geomagneticMatrix != null && accelerometerValues != null) {

        float[] R = new float[16];
        float[] I = new float[16];
        float[] outR = new float[16];

        //Get the rotation matrix, then remap it from camera surface to world coordinates
        SensorManager.getRotationMatrix(R, I, accelerometerValues, geomagneticMatrix);
        SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR);
        float values[] = new float[4];
        SensorManager.getOrientation(outR,values);
        float direction = normalizeDegrees((float) Math.toDegrees(values[0]));
        float pitch = normalizeDegrees((float) Math.toDegrees(values[1]));
        float roll = normalizeDegrees((float) Math.toDegrees(values[2]));

        if((int)direction != (int)lastDirection){
            lastDirection = direction;
            for(CompassListener listener: listeners){
                listener.onDirectionChanged(lastDirection, pitch, roll);
            }
        }
    }
}

任何想法我做错了什么?我坦率地承认我不是 100% 理解这一点。我也不知道为什么 Google 不推荐使用方向传感器——这似乎是一个很普遍的愿望。

【问题讨论】:

    标签: android orientation accelerometer sensors


    【解决方案1】:

    您是否考虑过,当您从纵向变为横向时,加速度计轴会发生变化?就像 Y 轴变成 Z 轴等等。这可能是奇怪行为的来源之一。

    【讨论】:

    • 我已经想到了。这里将是 y 轴和 x 轴切换(z 总是在屏幕外)。但这似乎也没有正确移动 - 我已经将所有 3 个都转储到屏幕上,但它们都没有正确移动。即使工作的方向也像疯了一样跳跃——转弯后每隔 1 秒采样一次,读数可能会导致读数为 180、320、280、220、180、300 ......当它应该是 200ish 时。
    【解决方案2】:

    我似乎已经解决了它,或者至少将它改进到我知道问题所在的地步。我放入了一个过滤器,这样我就不会提供单个传感器读数,而是记住最后一次读数并对其应用增量。每个新的传感器点最多允许增加 5 度。这完全过滤掉了奇怪的跳跃,并迫使它收敛到一个值。我偶尔会看到奇怪的跳跃,但我认为我需要的是更复杂的过滤器。新代码:

    public void onSensorChanged(SensorEvent event) {
        if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
            return;
    
        switch (event.sensor.getType()) {
        case Sensor.TYPE_ACCELEROMETER:
            accelerometerValues = event.values.clone();
    
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            geomagneticMatrix = event.values.clone();
            break;
        }   
    
        if (geomagneticMatrix != null && accelerometerValues != null) {
    
            float[] R = new float[16];
            float[] I = new float[16];
            float[] outR = new float[16];
    
            //Get the rotation matrix, then remap it from camera surface to world coordinates
            SensorManager.getRotationMatrix(R, I, accelerometerValues, geomagneticMatrix);
            SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR);
            float values[] = new float[4];
            SensorManager.getOrientation(outR,values);
    
            int direction = filterChange(normalizeDegrees(Math.toDegrees(values[0])));
            int pitch = normalizeDegrees(Math.toDegrees(values[1]));
            int roll = normalizeDegrees(Math.toDegrees(values[2]));
            if((int)direction != (int)lastDirection){
                lastDirection = (int)direction;
                lastPitch = (int)pitch;
                lastRoll = (int)roll;
                for(CompassListener listener: listeners){
                    listener.onDirectionChanged(lastDirection, pitch, roll);
                }
            }
        }
    }
    
    //Normalize a degree from 0 to 360 instead of -180 to 180
    private int normalizeDegrees(double rads){
        return (int)((rads+360)%360);
    }
    
    //We want to ignore large bumps in individual readings.  So we're going to cap the number of degrees we can change per report
    private int filterChange(int newDir){
        int change = newDir - lastDirection;
        int circularChange = newDir-(lastDirection+360);
        int smallestChange;
        if(Math.abs(change) < Math.abs(circularChange)){
            smallestChange = change;
        }
        else{
            smallestChange = circularChange;
        }
        smallestChange = Math.max(Math.min(change,5),-5);
        return lastDirection+smallestChange;
    }
    

    【讨论】:

    • 快速评论 - 3 和 -3 的值似乎提供了相当好的反弹保护。
    猜你喜欢
    • 1970-01-01
    • 2014-07-14
    • 2021-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多