Sensores de movimento

A plataforma Android oferece vários sensores que permitem monitorar o movimento de um dispositivo.

O valor as arquiteturas possíveis variam de acordo com o tipo de sensor:

  • A gravidade, a aceleração linear, o vetor de rotação, o movimento significativo e a taxa de aprendizado e os sensores de detecção de passos são baseados em hardware com base em software.
  • Os sensores de acelerômetro ou giroscópio sempre têm hardware como base.

A maioria dos dispositivos Android tem um acelerômetro, e muitos agora incluem um giroscópio A disponibilidade dos sensores baseados em software porque muitas vezes dependem de um ou mais sensores de hardware para derivar dados. Dependendo do dispositivo, esses sensores baseados em software podem derivar dados do acelerômetro e do magnetômetro ou do giroscópio.

Os sensores de movimento são úteis para monitorar o movimento do dispositivo, como inclinação, trepidação, rotação ou balanço. O movimento é geralmente um reflexo de entrada direta do usuário (por exemplo, um usuário direcionando um um carro em um jogo ou um usuário controlando uma bola em um jogo), mas também pode ser um reflexo da ambiente físico em que o dispositivo está (por exemplo, movendo-se com você enquanto dirige seu carro). No primeiro caso, você está monitorando o movimento em relação ao frame de referência do dispositivo. ou o frame de referência do seu aplicativo. No segundo caso, você está monitorando o movimento em relação referência do mundo. Os sensores de movimento por si só não costumam ser usados para monitorar na posição do dispositivo, mas podem ser usadas com outros sensores, como o de campo geomagnético, para determinam a posição de um dispositivo em relação ao frame de referência mundial (consulte Sensores de posição para mais informações).

Todos os sensores de movimento retornam matrizes multidimensionais de valores do sensor para cada SensorEvent. Por exemplo, durante um único evento de sensor, o acelerômetro retorna dados de força de aceleração para os três eixos coordenados, e o giroscópio retorna a taxa de rotação dados para os três eixos coordenados. Esses valores de dados são retornados em uma matriz float. (values) junto com outros SensorEvent parâmetros. A tabela 1 resume os sensores de movimento disponíveis na plataforma Android.

Tabela 1. Sensores de movimento compatíveis com a Plataforma Android.

Sensor Dados de eventos do sensor Descrição Unidades de medida
TYPE_ACCELEROMETER SensorEvent.values[0] Força de aceleração ao longo do eixo X (incluindo a gravidade). m/s2
SensorEvent.values[1] Força de aceleração ao longo do eixo Y (incluindo a gravidade).
SensorEvent.values[2] Força de aceleração ao longo do eixo Z (incluindo a gravidade).
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] Aceleração medida ao longo do eixo X sem nenhuma compensação de tendência. m/s2
SensorEvent.values[1] Aceleração medida ao longo do eixo Y sem nenhuma compensação de tendência.
SensorEvent.values[2] Aceleração medida ao longo do eixo Z sem nenhuma compensação de tendência.
SensorEvent.values[3] Aceleração medida ao longo do eixo X com estimativa de compensação de tendência.
SensorEvent.values[4] Aceleração medida ao longo do eixo Y com estimativa de compensação de tendência.
SensorEvent.values[5] Aceleração medida ao longo do eixo Z com estimativa de compensação de tendência.
TYPE_GRAVITY SensorEvent.values[0] Força da gravidade ao longo do eixo X. m/s2
SensorEvent.values[1] Força da gravidade ao longo do eixo Y.
SensorEvent.values[2] Força da gravidade ao longo do eixo Z.
TYPE_GYROSCOPE SensorEvent.values[0] Taxa de rotação ao redor do eixo X. rad/s
SensorEvent.values[1] Taxa de rotação ao redor do eixo Y.
SensorEvent.values[2] Taxa de rotação ao redor do eixo Z.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] Taxa de rotação (sem compensação de deslocamento) ao redor do eixo X. rad/s
SensorEvent.values[1] Taxa de rotação (sem compensação de deslocamento) ao redor do eixo Y.
SensorEvent.values[2] Taxa de rotação (sem compensação de deslocamento) ao redor do eixo Z.
SensorEvent.values[3] Deslocamento estimado ao redor do eixo X.
SensorEvent.values[4] Deslocamento estimado ao redor do eixo Y.
SensorEvent.values[5] Deslocamento estimado ao redor do eixo Z.
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] Força de aceleração ao longo do eixo X (excluindo a gravidade). m/s2
SensorEvent.values[1] Força de aceleração ao longo do eixo Y (excluindo a gravidade).
SensorEvent.values[2] Força de aceleração ao longo do eixo Z (excluindo a gravidade).
TYPE_ROTATION_VECTOR SensorEvent.values[0] Componente do vetor de rotação ao longo do eixo X (X * sen (θ / 2)). Sem unidade
SensorEvent.values[1] Componente do vetor de rotação ao longo do eixo Y (Y * sen (θ / 2)).
SensorEvent.values[2] Componente do vetor de rotação ao longo do eixo Z (Z * sen (θ / 2)).
SensorEvent.values[3] Componente escalar do vetor de rotação ((cos (\t/2)).1
TYPE_SIGNIFICANT_MOTION N/A N/A N/A
TYPE_STEP_COUNTER SensorEvent.values[0] Número de passos dados pelo usuário desde a última reinicialização enquanto o sensor estava ativado foi ativado. Etapas
TYPE_STEP_DETECTOR N/A N/A N/A

1 O componente escalar é um valor opcional.

Os sensores de vetor de rotação e de gravidade são os sensores mais usados para movimento detecção e monitoramento. O sensor de vetor rotacional é particularmente versátil e pode ser usado para uma ampla gama de tarefas relacionadas a movimentos, como detecção de gestos, monitoramento de mudanças angulares e para monitorar mudanças de orientação relativa. Por exemplo, o sensor de vetor rotacional é ideal se você estejam desenvolvendo um jogo, um aplicativo de realidade aumentada, uma bússola bidimensional ou tridimensional; ou um app de estabilização de câmera. Na maioria dos casos, usar esses sensores é melhor o acelerômetro e o sensor de campo geomagnético ou o sensor de orientação.

Sensores do Android Open Source Project

O Android Open Source Project (AOSP) oferece três sensores de movimento baseados em software: a gravidade de aceleração, de aceleração linear e de vetor de rotação. Esses sensores foram atualizados em O Android 4.0 e agora usam o giroscópio do dispositivo (além de outros sensores) para melhorar a estabilidade e desempenho. Se quiser testar esses sensores, você pode identificá-los usando os métodos getVendor() e getVersion(). (o fornecedor é Google LLC; o número da versão é 3). Identificar esses sensores por fornecedor e o número da versão é necessário porque o sistema Android considera esses três sensores como secundários ou sensores. Por exemplo, se um fabricante de dispositivos fornecer um sensor de gravidade próprio, o AOSP o sensor de gravidade aparece como um sensor de gravidade secundário. Todos esses três sensores dependem giroscópio: se um dispositivo não tiver um giroscópio, esses sensores não aparecerão e não serão disponíveis para uso.

Usar o sensor de gravidade

O sensor de gravidade fornece um vetor tridimensional indicando que direção e magnitude da gravidade. Normalmente, esse sensor é usado para determinar a orientação relativa do dispositivo no espaço. O código a seguir mostra como acesse uma instância do sensor de gravidade padrão:

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

As unidades são as mesmas usadas pela aceleração sensor (m/s2), e o sistema de coordenadas é o mesmo usado pelo sensor de aceleração.

Observação:quando um dispositivo está em repouso, a saída do sensor de gravidade deve ser idêntico ao do acelerômetro.

Usar o acelerômetro linear

O sensor de aceleração linear oferece um vetor tridimensional representando a aceleração ao longo de cada eixo do dispositivo, excluindo a gravidade. Você pode usar esse valor para realizar a detecção de gestos. O valor também pode servir como entrada para um sistema de navegação por inércia, que usa o cálculo morto. O código a seguir mostra como ter uma instância do sensor de aceleração linear padrão:

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

Conceitualmente, esse sensor fornece dados de aceleração de acordo com o seguinte: relacionamento:

linear acceleration = acceleration - acceleration due to gravity

Normalmente, esse sensor é usado quando você quer obter dados de aceleração sem a influência de gravidade. Por exemplo, ele pode ser usado para verificar a velocidade do seu carro. O modelo o sensor de aceleração sempre tem um deslocamento que você precisa remover. A maneira mais simples de fazer isso para criar uma etapa de calibração no aplicativo. Durante a calibragem, você pode pedir ao usuário para definir o dispositivo em uma mesa e, em seguida, ler os deslocamentos dos três eixos. Depois, subtraia esse valor de deslocamento das leituras diretas do sensor de aceleração para chegar à e aceleração.

A coordenada do sensor system é o mesmo usado pelo sensor de aceleração, assim como as unidades de medida (m/s2).

Usar o sensor de vetor de rotação

O vetor de rotação representa a orientação do dispositivo como uma combinação de um ângulo e uma eixo, em que o dispositivo girou através de um ângulo {2/} ao redor de um eixo (x, y ou z). O seguinte mostra como ter uma instância do sensor vetorial de rotação padrão:

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

Os três elementos do vetor de rotação são expressados da seguinte forma:

X * sen (θ / 2), Y * sen (θ / 2), Z * sen (θ / 2)

Em que a magnitude do vetor de rotação é igual a sen ( {2/} / 2) e a direção do vetor de rotação é igual à direção do eixo de rotação.

Figura 1. Sistema de coordenadas usado pelo sensor do vetor de rotação.

Os três elementos do vetor de rotação são iguais aos três últimos componentes de uma unidade quatérnio (cos(instituição/2), x*sen(ponto 3) / 2, y*sen(ponto do polígono/2), z*sen(instituição/2)). Os elementos do vetor de rotação são sem unidade. Os eixos X, Y e Z são definidos da mesma forma que o sensor de aceleração. A referência é definido como uma base ortonormal direta (veja a figura 1). Esse sistema de coordenadas tem as seguintes características:

  • X é definido como o produto vetorial Y x Z. Ela é tangencial à no local atual do dispositivo e aponta aproximadamente para o leste.
  • Y é tangencial ao solo na localização atual do dispositivo e aponta na direção do geomagnético Polo Norte.
  • Z aponta em direção ao céu e é perpendicular ao plano do solo.

Para obter um exemplo de aplicativo que mostra como usar o sensor de vetor de rotação, consulte RotaçãoVectorDemo.java.

Usar o sensor de movimento significativo

O sensor de movimento significativo aciona um evento sempre que esse movimento é detectado e ele se desativa automaticamente. Um movimento significativo é aquele que pode levar a uma mudança na a localização do usuário; por exemplo, caminhar, andar de bicicleta ou sentar em um carro em movimento. O código a seguir mostra como ter uma instância do sensor de movimento significativo padrão e como registrar um evento ouvinte:

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 mais informações, consulte TriggerEventListener.

Usar o sensor contador de passos

O sensor contador de passos informa o número de passos do usuário desde a última reinicialização enquanto o sensor estava ativado. O contador de passos tem mais latência (até 10 segundos), porém maior maior do que o sensor detector de passos.

Observação : é necessário declarar o ACTIVITY_RECOGNITION permissão para que seu app use este sensor em dispositivos que executam Android 10 (nível 29 da API) ou mais recente.

O código a seguir mostra como ter uma instância da etapa padrão sensor de contador:

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 economizar bateria em dispositivos que executam seu app, use o Classe JobScheduler para recuperar o valor atual da ao sensor contador de passos em um intervalo específico. Embora diferentes tipos de apps precisar de diferentes intervalos de leitura do sensor, faça esse intervalo o o máximo possível, a menos que seu aplicativo exija dados em tempo real do sensor.

Usar o sensor detector de passos

O sensor detector de passos aciona um evento sempre que o usuário dá um passo. A latência é deve ser inferior a 2 segundos.

Observação : é necessário declarar o ACTIVITY_RECOGNITION permissão para que seu app use este sensor em dispositivos que executam Android 10 (nível 29 da API) ou mais recente.

O código a seguir mostra como ter uma instância da etapa padrão 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);

Trabalhar com dados brutos

Os sensores a seguir oferecem ao app dados brutos sobre as camadas linear e forças rotacionais aplicadas ao dispositivo. Para usar os valores de esses sensores de modo eficaz, é preciso filtrar os fatores do ambiente, como a gravidade. Talvez também seja necessário aplicar um algoritmo de suavização à tendência de valores para reduzir o ruído.

Usar o acelerômetro

Um sensor de aceleração mede a aceleração aplicada ao dispositivo, incluindo a força gravidade. O código a seguir mostra como ter uma instância do sensor de aceleração padrão:

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

Observação : caso o app seja destinado ao Android 12 (nível 31 da API) ou mais alto, esse sensor com limitação de taxa.

Conceitualmente, um sensor de aceleração determina a aceleração aplicada a um dispositivo (Ad), medindo as forças aplicadas ao sensor (Fs) usando o seguinte relacionamento:

A_D=-(1/mass)∑F_S

No entanto, a força da gravidade está sempre influenciando a aceleração medida de acordo com a o seguinte relacionamento:

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

Por esse motivo, quando o dispositivo está sentado em uma mesa (e não acelerando), o o acelerômetro lê uma magnitude de g = 9,81 m/s2. Da mesma forma, quando o dispositivo está queda livre e, portanto, acelerando rapidamente em direção ao solo a 9,81 m/s2, sua o acelerômetro lê uma magnitude de g = 0 m/s2. Portanto, para avaliar a aceleração real do dispositivo, a contribuição da força da gravidade deve ser removida os dados do acelerômetro. Isso pode ser feito por meio da aplicação de um filtro de alta passagem. Por outro lado, um intervalo de filtro pode ser usado para isolar a força da gravidade. O exemplo a seguir mostra como fazer isso:

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

Observação:é possível usar muitas técnicas diferentes para filtrar os dados do sensor. O exemplo de código acima usa uma constante de filtro simples (Alfa) para criar um filtro de baixa passagem. Este filtro é derivada de uma constante de tempo (t), que é uma representação aproximada da latência o filtro adiciona aos eventos do sensor e à taxa de entrega de eventos do sensor (dt). O exemplo de código usa um valor Alfa de 0,8 para fins de demonstração. Se você usar esse método de filtragem, poderá ser necessário para escolher outro valor Alfa.

Os acelerômetros usam a coordenada padrão do sensor Google Workspace. Na prática, isso significa que as condições a seguir se aplicam quando um dispositivo sobre uma mesa na orientação natural:

  • Se você empurrar o dispositivo no lado esquerdo (para que ele se mova para a direita), o valor de aceleração x é positivo.
  • Se você empurrar o dispositivo na parte inferior (para que ele se afaste de você), o valor de aceleração y será positiva.
  • Se você empurrar o dispositivo em direção ao céu com uma aceleração de A m/s2, o O valor de aceleração z é igual a A + 9,81, que corresponde à aceleração do dispositivo (+A). m/s2) menos a força da gravidade (-9,81 m/s2).
  • O dispositivo estacionário terá um valor de aceleração de +9,81, o que corresponde ao aceleração do dispositivo (0 m/s2 menos a força da gravidade, que é -9,81 m/s2).

Em geral, o acelerômetro é um bom sensor a ser usado, caso você esteja monitorando o movimento do dispositivo. Quase todos os celulares e tablets Android têm um acelerômetro e ele usa cerca de 10 vezes menos potência que os outros. Uma desvantagem é que talvez seja necessário implementar filtros passa-baixo e passa-alto para eliminar forças gravitacionais e reduzir o ruído.

Usar o giroscópio

O giroscópio mede a taxa de rotação em rad/s em torno dos eixos x, y e e z. O código a seguir mostra como ter uma instância do giroscópio padrão:

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

Observação : caso o app seja destinado ao Android 12 (nível 31 da API) ou mais alto, esse sensor com limitação de taxa.

O sistema de coordenadas do sensor. é o mesmo usado para o sensor de aceleração. A rotação é positiva nas sentido anti-horário ou seja, um observador olhando de algum local positivo nos eixos x, y ou z em um dispositivo posicionado na origem informaria rotação positiva se o dispositivo parecia estar girando em sentido anti-horário. Esta é a definição matemática padrão de rotação positiva e não é o mesmo que a definição para rolo usado pelo sensor de orientação.

Normalmente, o resultado do giroscópio é integrado ao longo do tempo para calcular a rotação a mudança de ângulos ao longo do tempo. Exemplo:

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

Os giroscópios padrão fornecem dados rotacionais brutos sem filtragem ou correção de ruído. desvio (viés). Na prática, o deslocamento e o ruído do giroscópio introduzem erros que precisam ser compensado. Geralmente, o desvio (viés) e o ruído são determinados pelo monitoramento de outros sensores, como como o sensor de gravidade ou o acelerômetro.

Usar o giroscópio sem calibração

O giroscópio não calibrado é semelhante ao giroscópio, exceto que nenhuma compensação de deslocamento de giroscópio é aplicada à taxa de rotação. Calibração de fábrica e a compensação de temperatura ainda são aplicadas à taxa de rotação. Os dados não calibrados o giroscópio é útil para o pós-processamento e a fusão de dados de orientação. Em geral, gyroscope_event.values[0] vai estar perto de uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3]. Ou seja,

calibrated_x ~= uncalibrated_x - bias_estimate_x

Observação:sensores não calibrados fornecem resultados mais brutos e podem incluir algum viés, mas suas medições contêm menos saltos das correções aplicadas calibragem. Alguns aplicativos podem preferir esses resultados não calibrados como mais suaves e mais confiáveis. Por exemplo, se um aplicativo está tentando conduzir a própria fusão de sensores, introduzir calibragens pode realmente distorcer os resultados.

Além das taxas de rotação, o giroscópio sem calibração também fornece a estimativa deslocamento em torno de cada eixo. O código a seguir mostra como receber uma instância do giroscópio sem calibração:

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

Outros exemplos de código

A A amostra BatchStepSensor demonstra com mais detalhes o uso das APIs abordadas nesta página.

Leia também