1

私がしたいのは、電話が「自然な」向きから離れたときに、座標系を再マッピングすることです。そのため、携帯電話を横向きで使用している場合、縦向きに保持されている場合と同じ値を読み取る必要があります。

回転が に等しいかどうかを確認していますSurface.ROTATION_90。そうであれば、座標系を再マッピングします。

私はそれを適切に行う方法をよく理解していないことを認め、少しのガイダンスを使用できます.

したがって、次の 2 つのメソッドを実行する必要があります。

SensorManager.getRotationMatrix(inR, I, grav, mag); 
SensorManager.remapCoordinateSystem(inR, SensorManager.AXIS_Y,SensorManager.AXIS_MINUS_X, outR);

これらのメソッドに渡すには何が必要ですか? 新しい float 配列を作成し、orientationsensor データだけを mag フィールドに渡しましたが、機能しませんでした。そこで、加速度センサーと磁場センサーの両方を登録しました。それらの両方からgetRotatioMatrixメソッドにデータをフィードすると、常に取得されますNullPointerException(JavaDocには、一部の引数がnullになる可能性があると記載されていますが)。各引数にデータを渡そうとしても、NullPointerException.

私の質問は、getRotationMatrix メソッドに渡す必要がある適切なデータは何ですか?

4

2 に答える 2

6

これを行うための非常に簡単な方法は、SDK サンプルAccelerometerPlayで使用されている方法であることがわかりました。

最初に、たとえば onResume() で、次のような表示を取得します。

WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mDisplay = windowManager.getDefaultDisplay();

次に、 onSensorChanged() で次の簡単なコードを使用できます。

@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
        return;

    switch (mDisplay.getRotation()) {
        case Surface.ROTATION_0:
            mSensorX = event.values[0];
            mSensorY = event.values[1];
            break;
        case Surface.ROTATION_90:
            mSensorX = -event.values[1];
            mSensorY = event.values[0];
            break;
        case Surface.ROTATION_180:
            mSensorX = -event.values[0];
            mSensorY = -event.values[1];
            break;
        case Surface.ROTATION_270:
            mSensorX = event.values[1];
            mSensorY = -event.values[0];
            break;
    }
}

これが役立つことを願っています。

于 2013-07-23T14:31:12.087 に答える
0

これは私のコードで、NPE なしで動作します。リスナーは 1 つしかありませんが、両方のセンサー (ACCELEROMETER と MAGNETICFIELD) をリッスンするには、それを登録する必要があることに注意してください。

private SensorEventListener mOrientationSensorsListener = new SensorEventListener() {

    private float[] mR = new float[9];
    private float[] mRemappedR = new float[9];
    private float[] mGeomagneticVector = new float[3];
    private float[] mGravityVector = new float[3];

    @Override
    public void onSensorChanged(SensorEvent event) {
        synchronized(this) {
            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                mGravityVector = Util.exponentialSmoothing(event.values, mGravityVector, 0.2f);
            } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                mGeomagneticVector = Util.exponentialSmoothing(event.values, mGeomagneticVector, 0.5f);

                SensorManager.getRotationMatrix(mR, null, mGravityVector, mGeomagneticVector);
                SensorManager.remapCoordinateSystem(mR, SensorManager.AXIS_Y,SensorManager.AXIS_MINUS_X, mRemappedR);
            }
        }
    }

このexponentialSmoothingメソッドは、センサーの結果をある程度平滑化して、次のように表示します (アルファ値は 0 から 1 まで可能で、1 は平滑化がまったくないことを意味します)。

public static float[] exponentialSmoothing(float[] input, float[] output, float alpha) {
    for (int i=0; i<input.length; i++) {
        output[i] = output[i] + alpha * (input[i] - output[i]);
    }
    return output;
} 

synchronizedちょっとしたことですが、それが必要かどうかはわかりません。どこかで読んで追加してください。

于 2012-07-22T05:56:29.910 に答える