Pergunta

Tenho que escrever um aplicativo de bússola no Android.A única coisa que o usuário vê na tela é um cubo com uma parede vermelha que deve apontar para o norte.Isso não é importante.O importante é que preciso girar esse cubo de acordo com a rotação do próprio dispositivo, para que a parede vermelha continue apontando para o norte, não importa como o telefone esteja sendo segurado.Meu código é simples e direto:

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

Eu adicionei esta variável de direção extra que simplesmente armazena se o display do telefone está apontando para baixo ou para cima.Não sei se preciso, mas parece corrigir alguns bugs.estou usando o SensorSimulador para Android, mas sempre que meu controle deslizante de pitch fica no intervalo [-90, 90], as outras variáveis ​​se misturam.É como se eles tivessem um deslocamento de 180.Mas não consigo detectar quando estou neste intervalo porque o intervalo do tom é de -90 a 90, então posso mover o controle deslizante da esquerda para escrever e estarei sempre nesse intervalo.

Isso tudo foi apenas para mostrar o quão longe meu código avançou.Não estou dizendo como este problema deve ser resolvido porque provavelmente apenas me levarei a um beco sem saída.Veja, estou tentando escrever esse aplicativo há 3 dias e você pode imaginar como meu chefe está chateado.Eu li todos os tipos de tutoriais e tentei todas as fórmulas que pude encontrar ou imaginar.Então, por favor, me ajude.Tudo o que preciso fazer é saber girar meu cubo, cujos ângulos de rotação são ÂNGULOS DE EULER em graus.

Foi útil?

Solução

Aqui está um código que escrevi para fazer algo bem semelhante, realmente me preocupando apenas com a rotação do dispositivo na direção de rotação.Espero que ajude!Ele apenas usa os valores do acelerômetro para determinar a inclinação, sem necessidade de obter orientação da visualização.

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);
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top