Преобразовать значения из Sensor.TYPE_ORIENTATION в углы Эйлера? - PullRequest
2 голосов
/ 01 октября 2010

Я должен написать приложение для компаса в 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;
        }
    }
}

Я добавил эту дополнительную переменную направления, которая просто хранит, указывает ли дисплей телефона вниз или вверх. Я не знаю, нужно ли мне это, но, похоже, это исправляет некоторые ошибки. Я использую SensorSimulator для Android, но всякий раз, когда мой ползунок высоты тона входит в интервал [-90, 90], другие переменные смешиваются. Как будто они получают 180 смещения. Но я не могу определить, когда я нахожусь в этом интервале, потому что диапазон высоты тона составляет от -90 до 90, поэтому я могу перемещать этот ползунок слева для записи, и я всегда буду в этом интервале.

Это все лишь для того, чтобы показать вам, как далеко продвинулся мой код. Я не говорю о том, как решить эту проблему, потому что я, вероятно, только загоню себя в тупик. Видите ли, я пытался написать это приложение уже 3 дня, и вы можете себе представить, как разозлился мой начальник. Я прочитал все виды учебников и попробовал каждую формулу, которую смог найти или придумать. Поэтому, пожалуйста, помогите мне. Все, что мне нужно сделать, это знать, как вращать мой куб, углы поворота которого равны УГЛОВЫМ УГЛАМ в градусах.

1 Ответ

3 голосов
/ 03 мая 2011

Вот код, который я написал, чтобы сделать что-то похожее, действительно заботясь только о вращении устройства в направлении вращения. Надеюсь, поможет! Он просто использует значения акселерометра для определения высоты тона, нет необходимости получать ориентацию вида.

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