Sensores de movimiento

La plataforma de Android ofrece varios sensores que permiten supervisar el movimiento de un dispositivo.

Los sensores arquitecturas posibles varían según el tipo de sensor:

  • La gravedad, la aceleración lineal, el vector de rotación, el movimiento significativo, el paso contador y detector de pasos se basan en hardware o basada en software.
  • Los sensores del acelerómetro y del giroscopio siempre están basados en hardware.

La mayoría de los dispositivos con Android tienen un acelerómetro, y muchos ahora incluyen un giroscopio. La disponibilidad de los sensores basados en software es mayor variable porque, a menudo, dependen de uno o más sensores de hardware para derivar su de datos no estructurados. Según el dispositivo, estos sensores basados en software pueden obtener del acelerómetro y magnetómetro o del giroscopio.

Los sensores de movimiento son útiles para supervisar los movimientos del dispositivo, como la inclinación, la vibración, la rotación o columpio. El movimiento suele ser un reflejo de la entrada directa del usuario (por ejemplo, un usuario que dirige un un auto en un juego o un usuario que controla una pelota), pero también puede ser un reflejo del entorno físico en el que se encuentra el dispositivo (por ejemplo, moviéndose con usted mientras conduce) tu automóvil). En el primer caso, supervisarás un movimiento relacionado con el marco de referencia del dispositivo. o el marco de referencia de tu aplicación; En el segundo caso, estás monitoreando el movimiento relacionado con el marco de referencia del mundo. Los sensores de movimiento por sí solos no suelen usarse para supervisar del dispositivo, pero se pueden usar con otros sensores, como el sensor de campos geomagnéticos, para determinar la posición de un dispositivo respecto del marco de referencia mundial (consulta Sensores de posición para obtener más información información).

Todos los sensores de movimiento muestran arrays multidimensionales de valores de sensores para cada SensorEvent. Por ejemplo, durante un evento de sensor único, el acelerómetro devuelve datos de fuerza de aceleración para los tres ejes de coordenadas, y el giroscopio muestra la tasa de rotación datos para los tres ejes de coordenadas. Estos valores de datos se muestran en un array float. (values) y otros SensorEvent parámetros. En la tabla 1, se resumen los sensores de movimiento disponibles en la plataforma Android.

Tabla 1: Sensores de movimiento compatibles con la plataforma de Android.

Sensor Datos del evento del sensor Descripción Unidades de medición
TYPE_ACCELEROMETER SensorEvent.values[0] Indica la fuerza de aceleración en el eje x (incluida la gravedad). m/s2
SensorEvent.values[1] Indica la fuerza de aceleración en el eje Y (incluida la gravedad).
SensorEvent.values[2] Indica la fuerza de aceleración en el eje z (incluida la gravedad).
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] Indica la aceleración medida en el eje X sin compensación de sesgo. m/s2
SensorEvent.values[1] Indica la aceleración medida en el eje Y sin compensación de sesgo.
SensorEvent.values[2] Indica la aceleración medida en el eje Z sin compensación de sesgo.
SensorEvent.values[3] Indica la aceleración medida en el eje X con compensación de sesgo estimada.
SensorEvent.values[4] Indica la aceleración medida en el eje Y con compensación de sesgo estimada.
SensorEvent.values[5] Indica la aceleración medida en el eje Z con compensación de sesgo estimada.
TYPE_GRAVITY SensorEvent.values[0] Indica la fuerza de gravedad en el eje X. m/s2
SensorEvent.values[1] Indica la fuerza de gravedad en el eje y.
SensorEvent.values[2] Indica la fuerza de gravedad en el eje z.
TYPE_GYROSCOPE SensorEvent.values[0] Indica la rotación alrededor del eje x. rad/s
SensorEvent.values[1] Indica la rotación alrededor del eje y.
SensorEvent.values[2] Indica la rotación alrededor del eje z.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] Indica la velocidad de rotación (sin compensación de variación) alrededor del eje x. rad/s
SensorEvent.values[1] Indica la velocidad de rotación (sin compensación de variación) alrededor del eje y.
SensorEvent.values[2] Indica la velocidad de rotación (sin compensación de variación) alrededor del eje z.
SensorEvent.values[3] Indica la variación estimada alrededor del eje x.
SensorEvent.values[4] Indica la variación estimada alrededor del eje y.
SensorEvent.values[5] Indica la variación estimada alrededor del eje z.
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] Indica la fuerza de aceleración en el eje x (sin incluir la gravedad). m/s2
SensorEvent.values[1] Indica la fuerza de aceleración en el eje y (sin incluir la gravedad).
SensorEvent.values[2] Indica la fuerza de aceleración en el eje z (sin incluir la gravedad).
TYPE_ROTATION_VECTOR SensorEvent.values[0] Indica el componente vectorial de rotación junto al eje x (x * sin(θ/2)). Sin unidades
SensorEvent.values[1] Indica el componente vectorial de rotación junto al eje y (y * sin(θ/2)).
SensorEvent.values[2] Indica el componente vectorial de rotación junto al eje z (z * sin(θ/2)).
SensorEvent.values[3] Componente escalar del vector de rotación ((cos(XYZ/2)).1
TYPE_SIGNIFICANT_MOTION N/A N/A N/A
TYPE_STEP_COUNTER SensorEvent.values[0] Cantidad de pasos que dio el usuario desde el último reinicio mientras el sensor se activó. Pasos
TYPE_STEP_DETECTOR N/A N/A N/A

1 El componente escalar es un valor opcional.

El sensor vectorial de rotación y el sensor de gravedad son los sensores más utilizados para el movimiento y supervisión de los datos. El sensor vectorial de rotación es muy versátil y se puede usar para una amplia gama de tareas relacionadas con el movimiento, como detectar gestos, controlar cambios angulares y y supervisar cambios de orientación relativos. Por ejemplo, el sensor vectorial de rotación es ideal si están desarrollando un juego, una aplicación de realidad aumentada, una brújula bidimensional o tridimensional, o una app de estabilización de cámara. En la mayoría de los casos, usar estos sensores es una mejor opción el acelerómetro y el sensor de campo geomagnético o el sensor de orientación.

Sensores del Proyecto de código abierto de Android

El Proyecto de código abierto de Android (AOSP) proporciona tres sensores de movimiento basados en software: un valor de aceleración lineal, y el del vector de rotación. Estos sensores se actualizaron en Android 4.0 y ahora usan el giroscopio de un dispositivo (además de otros sensores) para mejorar la estabilidad rendimiento. Si quieres probar estos sensores, puedes identificarlos mediante el método getVendor() y el método getVersion() (el proveedor es Google LLC; el número de versión es 3). La identificación de estos sensores por proveedor y y el número de versión es necesario porque el sistema Android considera que estos tres sensores son secundarios sensores. Por ejemplo, si un fabricante de dispositivos proporciona su propio sensor de gravedad, el AOSP se muestra como un sensor secundario. Estos tres sensores dependen de un giroscopio: si un dispositivo no tiene giroscopio, estos sensores no se muestran disponibles para su uso.

Cómo usar el sensor de gravedad

El sensor de gravedad proporciona un vector tridimensional que indica la dirección y magnitud de la gravedad. Por lo general, este sensor se usa para determinar la orientación relativa del dispositivo en el espacio. El siguiente código te muestra cómo Obtén una instancia del sensor de gravedad predeterminado:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);

Las unidades son las mismas que se usan en la (m/s2), y el sistema de coordenadas es el mismo que usa el y sensor de aceleración.

Nota: Cuando un dispositivo está en reposo, la salida del sensor de gravedad debería ser idéntica al acelerómetro.

Cómo usar el acelerómetro lineal

El sensor de aceleración lineal proporciona un vector tridimensional que representa la aceleración en cada eje del dispositivo, sin incluir la gravedad. Puedes usar este valor para realizar la detección de gestos. El valor también puede servir como entrada para un sistema de navegación inercial, que utiliza la confianza. El siguiente código muestra Cómo obtener una instancia del sensor de aceleración lineal predeterminado:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);

Conceptualmente, este sensor te proporciona datos de aceleración según el siguiente relación:

linear acceleration = acceleration - acceleration due to gravity

Este sensor se suele usar cuando se quieren obtener datos de aceleración sin la influencia de gravedad. Por ejemplo, puedes usarlo para ver a qué velocidad se mueve tu auto. El modelo lineal el sensor de aceleración siempre tiene un desplazamiento, que debes quitar. La forma más sencilla de hacerlo es para compilar un paso de calibración en tu aplicación. Durante la calibración, puedes pedirle al usuario que establezca el dispositivo sobre una mesa y leer los desplazamientos de los tres ejes. Luego, puedes restarle de las lecturas directas del sensor de aceleración para obtener la aceleración.

La coordenada del sensor del sistema es el mismo que usa el sensor de aceleración, al igual que las unidades de medida (m/s2).

Cómo usar el sensor vectorial de rotación

El vector de rotación representa la orientación del dispositivo como una combinación de un ángulo y una En este eje (x, y, o z) se rotó el dispositivo a través de un ángulo ndk. Lo siguiente código muestra cómo obtener una instancia del sensor vectorial de rotación predeterminado:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);

Los tres elementos del vector de rotación se expresan de la siguiente manera:

x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)

Donde la magnitud del vector de rotación es igual a sin(ParDo/2), y la dirección del es igual a la dirección del eje de rotación.

Figura 1: Sistema de coordenadas que usa el sensor vectorial de rotación.

Los tres elementos del vector de rotación son iguales a los últimos tres componentes de una unidad cuaternion (cos(ndk/2), x*sin(sencilla/2), y*sin(mate/2), z*sin(mate/2)). Los elementos del vector de rotación se sin unidades. Los ejes x, y y z se definen de la misma manera que el sensor de aceleración. La referencia se define como una base ortonormal directa (consulta la figura 1). Este sistema de coordenadas tiene las siguientes características:

  • X se define como el producto vectorial Y x Z. Es tangencial al en la ubicación actual del dispositivo y apunta aproximadamente al este.
  • Y es tangencial al suelo en la ubicación actual del dispositivo y apunta hacia la geomagnético Polo Norte.
  • Z apunta hacia el cielo y es perpendicular al plano terrestre.

Para ver una aplicación de ejemplo que muestre cómo usar el sensor vectorial de rotación, consulta RotationVectorDemo.java.

Cómo usar el sensor de movimiento significativo

El sensor de movimiento significativo activa un evento cada vez que se detecta y, luego, se inhabilita solo. Un movimiento significativo es un movimiento que puede llevar a un cambio en la la ubicación del usuario; como caminar, andar en bicicleta o viajar en automóvil. El siguiente código te muestra cómo obtener una instancia del sensor de movimiento significativo predeterminado y cómo registrar un evento objeto de escucha:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val mSensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION)
val triggerEventListener = object : TriggerEventListener() {
    override fun onTrigger(event: TriggerEvent?) {
        // Do work
    }
}
mSensor?.also { sensor ->
    sensorManager.requestTriggerSensor(triggerEventListener, sensor)
}

Java

private SensorManager sensorManager;
private Sensor sensor;
private TriggerEventListener triggerEventListener;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);

triggerEventListener = new TriggerEventListener() {
    @Override
    public void onTrigger(TriggerEvent event) {
        // Do work
    }
};

sensorManager.requestTriggerSensor(triggerEventListener, mSensor);

Para obtener más detalles, consulta la información de TriggerEventListener.

Cómo usar el sensor del contador de pasos

El sensor del contador de pasos indica la cantidad de pasos que dio el usuario desde el último reinicio mientras se activaba el sensor. El contador de pasos tiene más latencia (hasta 10 segundos), pero más que el sensor del detector de pasos.

Nota: Debes declarar el ACTIVITY_RECOGNITION permiso para que tu app use este sensor en dispositivos que se ejecutan Android 10 (nivel de API 29) o una versión posterior

En el siguiente código, se muestra cómo obtener una instancia del paso predeterminado contador de sensores:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);

Para conservar la batería de los dispositivos que ejecutan tu aplicación, debes utilizar la Clase JobScheduler de la que recuperarás el valor actual el sensor del contador de pasos en un intervalo específico. Aunque los diferentes tipos de apps requieren diferentes intervalos de lectura del sensor, debes hacer que este intervalo la mayor cantidad de tiempo posible, a menos que tu app requiera datos del sensor en tiempo real.

Cómo usar el sensor del detector de pasos

Este sensor activa un evento cada vez que el usuario da un paso. La latencia es se espera que sea inferior a 2 segundos.

Nota: Debes declarar el ACTIVITY_RECOGNITION permiso para que tu app use este sensor en dispositivos que se ejecutan Android 10 (nivel de API 29) o una versión posterior

En el siguiente código, se muestra cómo obtener una instancia del paso predeterminado sensor detector:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);

Cómo trabajar con datos sin procesar

Los siguientes sensores proporcionan a tu app datos sin procesar sobre las variables lineales de las fuerzas rotativas que se aplican al dispositivo. Para usar los valores de estos sensores de manera efectiva, debe filtrar los factores del entorno como la gravedad. Quizás también debas aplicar un algoritmo de suavizado a la tendencia de valores para reducir el ruido.

Cómo usar el acelerómetro

Un sensor de aceleración mide la aceleración aplicada al dispositivo, incluida la fuerza del gravedad. En el siguiente código, se muestra cómo obtener una instancia del sensor de aceleración predeterminado:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

Java

private SensorManager sensorManager;
private Sensor sensor;
  ...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

Nota: Si tu app se orienta a Android 12 (nivel de API 31) o más arriba, este sensor se con límite de frecuencia.

De forma conceptual, un sensor de aceleración determina la aceleración que se aplica a un dispositivo (Ad) midiendo las fuerzas que se aplican al sensor (Fs) con la siguiente relación:

A_D=-(1/masa)∑F_S

Sin embargo, la fuerza de la gravedad siempre influye en la aceleración medida de acuerdo con la siguiente relación:

A_D=-g-(1/masa)∑F_S

Por este motivo, cuando el dispositivo está apoyado sobre una mesa (y no acelerando), el el acelerómetro lee una magnitud de g = 9.81 m/s2. Del mismo modo, cuando el dispositivo está en caída libre y, por lo tanto, acelera rápidamente hacia el suelo a 9.81 m/s2, su el acelerómetro lee una magnitud de g = 0 m/s2. Por lo tanto, para medir la aceleración real del dispositivo, la contribución de la fuerza de gravedad debe eliminarse del los datos del acelerómetro. Esto puede lograrse aplicando un filtro de paso alto. Por el contrario, una técnica de paso bajo para aislar la fuerza de gravedad. En el siguiente ejemplo, se muestra cómo puedes hacer esto:

Kotlin

override fun onSensorChanged(event: SensorEvent) {
    // In this example, alpha is calculated as t / (t + dT),
    // where t is the low-pass filter's time-constant and
    // dT is the event delivery rate.

    val alpha: Float = 0.8f

    // Isolate the force of gravity with the low-pass filter.
    gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]
    gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]
    gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]

    // Remove the gravity contribution with the high-pass filter.
    linear_acceleration[0] = event.values[0] - gravity[0]
    linear_acceleration[1] = event.values[1] - gravity[1]
    linear_acceleration[2] = event.values[2] - gravity[2]
}

Java

public void onSensorChanged(SensorEvent event){
    // In this example, alpha is calculated as t / (t + dT),
    // where t is the low-pass filter's time-constant and
    // dT is the event delivery rate.

    final float alpha = 0.8;

    // Isolate the force of gravity with the low-pass filter.
    gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
    gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
    gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];

    // Remove the gravity contribution with the high-pass filter.
    linear_acceleration[0] = event.values[0] - gravity[0];
    linear_acceleration[1] = event.values[1] - gravity[1];
    linear_acceleration[2] = event.values[2] - gravity[2];
}

Nota: Puedes usar muchas técnicas diferentes para filtrar los datos de sensores. El ejemplo de código anterior utiliza una simple constante de filtro (Alfa) para crear un filtro de paso bajo. Este filtro deriva de una constante de tiempo (t), que es una representación aproximada de la latencia que el filtro se suma a los eventos del sensor y al índice de entrega de eventos del sensor (dt). La muestra de código usa un valor alfa de 0.8 con fines de demostración. Si usas este método de filtrado, es posible que para elegir un valor alfa diferente.

Los acelerómetros usan la coordenada del sensor estándar. de la aplicación. En la práctica, esto significa que se aplican las siguientes condiciones cuando se coloca un dispositivo sobre una tabla en su orientación natural:

  • Si empujas el dispositivo hacia la izquierda (de manera que se mueva hacia la derecha), el valor de aceleración x es positiva.
  • Si aprietas el dispositivo hacia abajo (para que se aleje de ti), el valor de aceleración y será positivo.
  • Si empujas el dispositivo hacia el cielo con una aceleración de A m/s2, el valor El valor de aceleración z equivale a A + 9.81, que corresponde a la aceleración del dispositivo (+A). m/s2) menos la fuerza de gravedad (-9.81 m/s2).
  • El dispositivo estacionario tendrá un valor de aceleración de +9.81, que corresponde al aceleración del dispositivo (0 m/s2 menos la fuerza de gravedad, que es -9.81 m/s2).

En general, se recomienda usar el acelerómetro para supervisar el movimiento del dispositivo. Casi todos los teléfonos celulares y tablets con Android tienen un acelerómetro y su uso es de 10 veces. menos energía que los otros sensores de movimiento. Una desventaja es que quizás debas implementar filtros de paso bajo y alto para eliminar las fuerzas gravitacionales y reducir el ruido.

Cómo usar el giroscopio

El giroscopio mide la velocidad de rotación en rad/s alrededor de la x, y, y eje z. En el siguiente código, se muestra cómo obtener una instancia del giroscopio predeterminado:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

Nota: Si tu app se orienta a Android 12 (nivel de API 31) o más arriba, este sensor se con límite de frecuencia.

El sistema de coordenadas del sensor es el mismo que se usa para el sensor de aceleración. La rotación es positiva en la en el sentido contrario a las manecillas del reloj; es decir, un observador que busca de alguna ubicación positiva en el eje x, y o z en un dispositivo posicionado en el origen informarían positiva cuando el dispositivo parezca rotar en el sentido contrario a las manecillas del reloj. Este es el definición matemática estándar de rotación positiva y no es lo mismo que la definición de que usa el sensor de orientación.

Por lo general, la salida del giroscopio se integra con el tiempo para calcular una rotación que describa el cambio de ángulos a lo largo del tiempo. Por ejemplo:

Kotlin

// Create a constant to convert nanoseconds to seconds.
private val NS2S = 1.0f / 1000000000.0f
private val deltaRotationVector = FloatArray(4) { 0f }
private var timestamp: Float = 0f

override fun onSensorChanged(event: SensorEvent?) {
    // This timestep's delta rotation to be multiplied by the current rotation
    // after computing it from the gyro sample data.
    if (timestamp != 0f && event != null) {
        val dT = (event.timestamp - timestamp) * NS2S
        // Axis of the rotation sample, not normalized yet.
        var axisX: Float = event.values[0]
        var axisY: Float = event.values[1]
        var axisZ: Float = event.values[2]

        // Calculate the angular speed of the sample
        val omegaMagnitude: Float = sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ)

        // Normalize the rotation vector if it's big enough to get the axis
        // (that is, EPSILON should represent your maximum allowable margin of error)
        if (omegaMagnitude > EPSILON) {
            axisX /= omegaMagnitude
            axisY /= omegaMagnitude
            axisZ /= omegaMagnitude
        }

        // Integrate around this axis with the angular speed by the timestep
        // in order to get a delta rotation from this sample over the timestep
        // We will convert this axis-angle representation of the delta rotation
        // into a quaternion before turning it into the rotation matrix.
        val thetaOverTwo: Float = omegaMagnitude * dT / 2.0f
        val sinThetaOverTwo: Float = sin(thetaOverTwo)
        val cosThetaOverTwo: Float = cos(thetaOverTwo)
        deltaRotationVector[0] = sinThetaOverTwo * axisX
        deltaRotationVector[1] = sinThetaOverTwo * axisY
        deltaRotationVector[2] = sinThetaOverTwo * axisZ
        deltaRotationVector[3] = cosThetaOverTwo
    }
    timestamp = event?.timestamp?.toFloat() ?: 0f
    val deltaRotationMatrix = FloatArray(9) { 0f }
    SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
    // User code should concatenate the delta rotation we computed with the current rotation
    // in order to get the updated rotation.
    // rotationCurrent = rotationCurrent * deltaRotationMatrix;
}

Java

// Create a constant to convert nanoseconds to seconds.
private static final float NS2S = 1.0f / 1000000000.0f;
private final float[] deltaRotationVector = new float[4]();
private float timestamp;

public void onSensorChanged(SensorEvent event) {
    // This timestep's delta rotation to be multiplied by the current rotation
    // after computing it from the gyro sample data.
    if (timestamp != 0) {
      final float dT = (event.timestamp - timestamp) * NS2S;
      // Axis of the rotation sample, not normalized yet.
      float axisX = event.values[0];
      float axisY = event.values[1];
      float axisZ = event.values[2];

      // Calculate the angular speed of the sample
      float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);

      // Normalize the rotation vector if it's big enough to get the axis
      // (that is, EPSILON should represent your maximum allowable margin of error)
      if (omegaMagnitude > EPSILON) {
        axisX /= omegaMagnitude;
        axisY /= omegaMagnitude;
        axisZ /= omegaMagnitude;
      }

      // Integrate around this axis with the angular speed by the timestep
      // in order to get a delta rotation from this sample over the timestep
      // We will convert this axis-angle representation of the delta rotation
      // into a quaternion before turning it into the rotation matrix.
      float thetaOverTwo = omegaMagnitude * dT / 2.0f;
      float sinThetaOverTwo = sin(thetaOverTwo);
      float cosThetaOverTwo = cos(thetaOverTwo);
      deltaRotationVector[0] = sinThetaOverTwo * axisX;
      deltaRotationVector[1] = sinThetaOverTwo * axisY;
      deltaRotationVector[2] = sinThetaOverTwo * axisZ;
      deltaRotationVector[3] = cosThetaOverTwo;
    }
    timestamp = event.timestamp;
    float[] deltaRotationMatrix = new float[9];
    SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
    // User code should concatenate the delta rotation we computed with the current rotation
    // in order to get the updated rotation.
    // rotationCurrent = rotationCurrent * deltaRotationMatrix;
}

Los giroscopios estándar proporcionan datos de rotación sin filtros ni correcciones de ruido. desviación (sesgo). En la práctica, el ruido y la desviación del giroscopio introducirán errores que se deben compensados. Por lo general, se determinan la desviación (sesgo) y el ruido mediante la supervisión de otros sensores, como que el sensor de gravedad o el acelerómetro.

Cómo usar el giroscopio no calibrado

El giroscopio no calibrado es similar al giroscopio. excepto que no se aplica ninguna compensación de giro a la velocidad de rotación. Calibración de fábrica y se sigue aplicando la compensación de temperatura a la velocidad de rotación. Los sensores no calibrados el giroscopio es útil para el posprocesamiento y la combinación de datos de orientación. En general, El gyroscope_event.values[0] se encontrará cerca de uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3] Es decir:

calibrated_x ~= uncalibrated_x - bias_estimate_x

Nota: Los sensores no calibrados proporcionan más resultados sin procesar y pueden incluyen cierto sesgo, pero sus mediciones contienen menos saltos de las correcciones aplicadas mediante calibración. Es posible que algunas aplicaciones prefieran estos resultados sin calibrar como más fluidos y más confiables. Por ejemplo, si una aplicación intenta realizar su propia fusión de sensores, pero, al introducir calibraciones, se pueden distorsionar los resultados.

Además de las tasas de rotación, el giroscopio no calibrado también proporciona la estimación oscila alrededor de cada eje. En el siguiente código, se muestra cómo obtener una instancia de la configuración giroscopio no calibrado:

Kotlin

val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED);

Muestras de código adicionales

El El ejemplo de BatchStepSensor demuestra aún más el uso de las APIs que se abordan en esta página.

También debes leer: