Pregunta

Tengo que escribir una aplicación Compass en Android. Lo único que el usuario ve en la pantalla es un cubo con una pared roja que tiene que apuntar hacia el norte. Esto no es importante. Lo importante es que necesito rotar ese cubo en consecuencia a la rotación del dispositivo en sí para que la pared roja continúe apuntando hacia el norte sin importar cómo se mantenga el teléfono. Mi código es simple y sencillo:

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

He agregado esta variable de dirección adicional que simplemente almacena si la pantalla del teléfono apunta hacia abajo o hacia arriba. No sé si lo necesito, pero parece solucionar algunos errores. Estoy usando el Sensorsimulador Para Android, pero cada vez que mi control deslizante se extiende en el intervalo [-90, 90], las otras variables se mezclan. Es como si obtuvieran un desplazamiento de 180. Pero no puedo detectar cuándo estoy en este intervalo porque el rango del campo es de -90 a 90, por lo que puedo mover ese control deslizante de la izquierda para escribir y siempre estaré en ese intervalo.

Todo esto fue solo para mostrarle cuán lejos ha avanzado mi código. No digo cómo se debe resolver este problema porque probablemente solo me incluiré en un callejón sin salida. Verá, he estado tratando de escribir esa aplicación durante 3 días, y puedes imaginar lo enojado que está mi jefe. He leído todo tipo de tutoriales y probé todas las fórmulas que pude encontrar o pensar. Así que por favor ayúdame. Todo lo que tengo que hacer es saber cómo rotar mi cubo, cuyos ángulos de rotación son ángulos de Euler en grados.

¿Fue útil?

Solución

Aquí hay algún código que escribí para hacer algo bastante similar, realmente solo se preocupa por la rotación del dispositivo en la dirección del rollo. ¡Espero eso ayude! Simplemente usa los valores del acelerómetro para determinar el tono, no es necesario obtener orientación de la vista.

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top