2

Androidでコンパスアプリを作成する必要があります。ユーザーが画面に表示するのは、北を向く必要のある赤い壁のある立方体だけです。これは重要ではありません。重要なのは、デバイス自体の回転に応じてその立方体を回転させて、電話がどのように保持されていても赤い壁が北を向くようにする必要があることです。私のコードは単純明快です:

@Override
public void onSensorChanged(SensorEvent event) {
    synchronized (this) {
        switch (event.sensor.getType()){
        case Sensor.TYPE_ACCELEROMETER:
            direction = event.values[2];
            break;
        case Sensor.TYPE_ORIENTATION:
            if (direction < 0) {
                angleX = event.values[1];
                angleY = -event.values[2];
                angleZ = event.values[0];
            } else {
                angleX = -event.values[1];
                angleY = -event.values[2];
                angleZ = event.values[0];   
            }
            break;
        }
    }
}

電話のディスプレイが下向きか上向きかを単純に格納するこの追加の方向変数を追加しました。必要かどうかはわかりませんが、いくつかのバグが修正されているようです。私はAndroid用のSensorSimulatorを使用していますが、ピッチスライダーが[-90、90]間隔になると、他の変数が混同されます。それは彼らが180オフセットを得るようなものです。しかし、ピッチの範囲が-90から90であるため、この間隔にいることを検出できません。そのため、スライダーを左から書き込みに移動でき、常にその間隔になります。

これはすべて、私のコードがどこまで進んだかを示すためだけのものでした。私はおそらく行き止まりに陥るだけなので、この問題をどのように解決すべきかを言っているのではありません。ほら、私はそのアプリを3日間書き込もうとしていて、上司がどれほど腹を立てているか想像できます。私はあらゆる種類のチュートリアルを読み、見つけたり考えたりできるすべての数式を試しました。だから私を助けてください。私がしなければならないのは、立方体を回転させる方法を知っていることだけです。その回転角は、度単位のオイラー角です。

4

1 に答える 1

3

これは私がかなり似たようなことをするために書いたいくつかのコードで、実際にはロール方向へのデバイスの回転だけを気にしています。それが役に立てば幸い!加速度計の値を使用してピッチを決定するだけで、ビューの向きを取得する必要はありません。

public void onSensorChanged(SensorEvent event) {
    float x = -1 * event.values[0] / SensorManager.GRAVITY_EARTH;
    float y = -1 * event.values[1] / SensorManager.GRAVITY_EARTH;
    float z = -1 * event.values[2] / SensorManager.GRAVITY_EARTH;

    float signedRawRoll = (float) (Math.atan2(x, y) * 180 / Math.PI);
    float unsignedRawRoll = Math.abs(signedRawRoll);
    float rollSign = signedRawRoll / unsignedRawRoll;
    float rawPitch = Math.abs(z * 180);

    // Use a basic low-pass filter to only keep the gravity in the accelerometer values for the X and Y axes
    // adjust the filter weight based on pitch, as roll is harder to define as pitch approaches 180.
    float filterWeight = rawPitch > 165 ? 0.85f : 0.7f;
    float newUnsignedRoll = filterWeight * Math.abs(this.roll) + (1 - filterWeight) * unsignedRawRoll;
    this.roll = rollSign * newUnsignedRoll;
    if (Float.isInfinite(this.roll) || Float.isNaN(this.roll)) {
        this.roll = 0;
    }
    this.pitch = filterWeight * this.pitch + (1 - filterWeight) * rawPitch;
    for (IAngleListener listener : listeners) {
        listener.deviceRollAndPitch(this.roll, this.pitch);
    }
}
于 2011-05-03T19:45:39.380 に答える