Sensori di movimento

La piattaforma Android mette a disposizione diversi sensori che ti consentono di monitorare il movimento di un dispositivo.

I sensori le architetture possibili variano in base al tipo di sensore:

  • Gravità, accelerazione lineare, vettore di rotazione, moto significativo, passo contatore e rilevatore di passi sono basati su hardware basate su software.
  • I sensori dell'accelerometro e del giroscopio sono sempre basati su hardware.

La maggior parte dei dispositivi Android è dotata di un accelerometro e molti ora includono un un giroscopio. La disponibilità dei sensori basati su software è sempre maggiore perché spesso si basano su uno o più sensori hardware per ricavare la loro e i dati di Google Cloud. A seconda del dispositivo, questi sensori basati su software possono ricavare la loro i dati provenienti dall'accelerometro e dal magnetometro o dal giroscopio.

I sensori di movimento sono utili per monitorare i movimenti del dispositivo, ad esempio l'inclinazione, lo scuotimento, la rotazione swing. Questo movimento riflette in genere l'input diretto dell'utente (ad esempio, un utente che indirizza una un'auto in un gioco o un utente che controlla una palla in una partita), ma può anche rispecchiare il ambiente fisico in cui il dispositivo è seduto (ad esempio, se si muove insieme a te durante la guida) dell'auto). Nel primo caso, monitori il movimento rispetto al frame di riferimento del dispositivo o il quadro di riferimento della tua applicazione; nel secondo caso, invece, stai monitorando il movimento rispetto il quadro di riferimento globale. I sensori di movimento da soli non sono generalmente utilizzati per monitorare la posizione del dispositivo, ma possono essere utilizzati con altri sensori, come il sensore di campo geomagnetico, per determinare la posizione di un dispositivo rispetto al sistema di riferimento globale (consulta la sezione Sensori di posizione per ulteriori informazioni informazioni).

Tutti i sensori di movimento restituiscono array multidimensionali di valori dei sensori per ogni SensorEvent. Ad esempio, durante un singolo evento del sensore, l'accelerometro restituisce i dati della forza di accelerazione per i tre assi coordinati e il giroscopio restituisce la velocità di rotazione per i tre assi di coordinate. Questi valori dei dati vengono restituiti in un array float (values) insieme ad altri SensorEvent parametri. La tabella 1 riassume i sensori di movimento disponibili sulla piattaforma Android.

Tabella 1. Sensori di movimento supportati dalla piattaforma Android.

Sensore Dati sugli eventi dei sensori Descrizione Unità di misura
TYPE_ACCELEROMETER SensorEvent.values[0] Forza di accelerazione lungo l'asse x (inclusa la gravità). m/s2
SensorEvent.values[1] Forza di accelerazione lungo l'asse y (inclusa la gravità).
SensorEvent.values[2] Forza di accelerazione lungo l'asse z (inclusa la gravità).
TYPE_ACCELEROMETER_UNCALIBRATED SensorEvent.values[0] Accelerazione misurata lungo l'asse X senza compensazione del bias. m/s2
SensorEvent.values[1] Accelerazione misurata lungo l'asse Y senza compensazioni bias.
SensorEvent.values[2] Accelerazione misurata lungo l'asse Z senza compensazione della distorsione.
SensorEvent.values[3] Accelerazione misurata lungo l'asse X con la compensazione dei bias stimata.
SensorEvent.values[4] Accelerazione misurata lungo l'asse Y con la compensazione dei bias stimata.
SensorEvent.values[5] Accelerazione misurata lungo l'asse Z con la compensazione del bias stimata.
TYPE_GRAVITY SensorEvent.values[0] Forza di gravità lungo l'asse x. m/s2
SensorEvent.values[1] Forza di gravità lungo l'asse y.
SensorEvent.values[2] Forza di gravità lungo l'asse z.
TYPE_GYROSCOPE SensorEvent.values[0] Frequenza di rotazione attorno all'asse x. rad/s
SensorEvent.values[1] Frequenza di rotazione attorno all'asse y.
SensorEvent.values[2] Frequenza di rotazione attorno all'asse z.
TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] Velocità di rotazione (senza compensazione della deviazione) attorno all'asse x. rad/s
SensorEvent.values[1] Frequenza di rotazione (senza compensazione della deviazione) attorno all'asse y.
SensorEvent.values[2] Frequenza di rotazione (senza compensazione della deviazione) attorno all'asse z.
SensorEvent.values[3] Deviazione stimata attorno all'asse x.
SensorEvent.values[4] Deviazione stimata attorno all'asse y.
SensorEvent.values[5] Deviazione stimata attorno all'asse z.
TYPE_LINEAR_ACCELERATION SensorEvent.values[0] Forza di accelerazione lungo l'asse x (esclusa la gravità). m/s2
SensorEvent.values[1] Forza di accelerazione lungo l'asse y (esclusa la gravità).
SensorEvent.values[2] Forza di accelerazione lungo l'asse z (esclusa la gravità).
TYPE_ROTATION_VECTOR SensorEvent.values[0] Componente del vettore di rotazione lungo l'asse x (x * sin(©/2)). Senza unità
SensorEvent.values[1] Componente del vettore di rotazione lungo l'asse y (y * sin(©/2)).
SensorEvent.values[2] Componente del vettore di rotazione lungo l'asse z (z * sin(©/2)).
SensorEvent.values[3] Componente scalare del vettore di rotazione ((cos(economico/2)).1
TYPE_SIGNIFICANT_MOTION N/D N/D N/D
TYPE_STEP_COUNTER SensorEvent.values[0] Numero di passi effettuati dall'utente dall'ultimo riavvio mentre il sensore è stata attivata. Passi
TYPE_STEP_DETECTOR N/D N/D N/D

1 Il componente scalare è un valore facoltativo.

Il sensore del vettore di rotazione e il sensore di gravità sono i sensori più utilizzati per il movimento il rilevamento e il monitoraggio. Il sensore vettoriale rotazionale è particolarmente versatile e può essere utilizzato un'ampia gamma di attività relative al movimento, come il rilevamento dei gesti, il monitoraggio del cambiamento angolare e monitorando le variazioni di orientamento relativo. Ad esempio, il sensore vettoriale rotazionale è ideale se stanno sviluppando un gioco, un'applicazione di realtà aumentata, una bussola bidimensionale o tridimensionale, o un'app di stabilizzazione della fotocamera. Nella maggior parte dei casi, l'utilizzo di questi sensori è una scelta migliore rispetto all'uso il sensore dell'accelerometro e del campo geomagnetico o il sensore di orientamento.

Sensori di Android Open Source Project

Android Open Source Project (AOSP) fornisce tre sensori di movimento basati su software: un sensore, un sensore di accelerazione lineare e un sensore del vettore di rotazione. Questi sensori sono stati aggiornati in Android 4.0 e ora utilizzano il giroscopio di un dispositivo (oltre ad altri sensori) per migliorare stabilità e le prestazioni dei dispositivi. Se vuoi provare questi sensori, puoi identificarli usando il metodo getVendor() e il metodo getVersion() (il fornitore è Google LLC; il numero di versione è 3). Identificare questi sensori per fornitore e numero di versione è necessario perché il sistema Android considera questi tre sensori secondari i sensori. Ad esempio, se un produttore di dispositivi fornisce il proprio sensore di gravità, l'AOSP sensore di gravità si presenta come sensore di gravità secondario. Tutti e tre questi sensori si basano giroscopio: se il dispositivo non dispone di un giroscopio, questi sensori non vengono visualizzati e non sono disponibili per l'uso.

Utilizzare il sensore di gravità

Il sensore di gravità fornisce un vettore tridimensionale che indica la direzione e magnitudine della gravità. Generalmente, questo sensore viene utilizzato per determinare l'orientamento relativo del dispositivo nello spazio. Il seguente codice mostra come un'istanza del sensore di gravità predefinito:

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

Le unità sono le stesse utilizzate dall'accelerazione (m/s2) e il sistema di coordinate è lo stesso utilizzato dal sensore sensore di accelerazione.

Nota:quando un dispositivo è fermo, l'uscita del sensore di gravità deve essere identica a quella dell'accelerometro.

Usare l'accelerometro lineare

Il sensore di accelerazione lineare fornisce un vettore tridimensionale che rappresenta l'accelerazione lungo ciascun asse dei dispositivi, esclusa la gravità. Puoi utilizzare questo valore per eseguire il rilevamento dei gesti. Il valore può anche essere utilizzato come input per di navigazione inerziale, che impiega i calcoli di base. Il seguente codice mostra come ottenere un'istanza del sensore di accelerazione lineare predefinito:

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

Concettualmente, questo sensore fornisce dati di accelerazione in base ai seguenti parametri relazione:

linear acceleration = acceleration - acceleration due to gravity

In genere si usa questo sensore per ottenere dati di accelerazione senza l'influenza di gravità. Ad esempio, questo sensore potrebbe essere usato per vedere a che velocità sta andando l'auto. Lineare del sensore di accelerazione ha sempre un offset, che è necessario rimuovere. Il modo più semplice per farlo è per creare un passaggio di calibrazione nella tua applicazione. Durante la calibrazione puoi chiedere all'utente di impostare il dispositivo su una tabella, per poi leggere gli offset di tutti e tre gli assi. Puoi quindi sottrarre dell'offset dalle letture dirette del sensore di accelerazione per ottenere il valore dell'accelerazione.

La coordinata del sensore sistema è uguale a quello utilizzato dal sensore di accelerazione, così come le unità di misura (m/s2).

Utilizza il sensore del vettore di rotazione

Il vettore di rotazione rappresenta l'orientamento del dispositivo come combinazione di un angolo e una , in cui il dispositivo è ruotato di un angolo Posizioni attorno a un asse (x, y o z). Le seguenti mostra come ottenere un'istanza del sensore vettoriale di rotazione predefinito:

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

I tre elementi del vettore di rotazione sono espressi come segue:

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

Dove la grandezza del vettore di rotazione è uguale a sin(©/2) e la direzione del vettore vettore di rotazione è uguale alla direzione dell'asse di rotazione.

Figura 1. Sistema di coordinate utilizzato dal sensore del vettore di rotazione.

I tre elementi del vettore di rotazione sono uguali alle ultime tre componenti di un'unità quaternione (cos(economico/2), x*sin(economico/2), y*sin(economico/2), z*sin(economico/2). Gli elementi del vettore di rotazione sono senza unità. Gli assi x, y e z sono definiti allo stesso modo del sensore di accelerazione. Il riferimento sistema di coordinate è definito come una base ortonormale diretta (vedi figura 1). Questo sistema di coordinate presenta le seguenti caratteristiche:

  • X è definito come il prodotto vettoriale Y x Z. È tangenziale al dal suolo rispetto alla posizione attuale del dispositivo e punti a circa est.
  • La Y è tangenziale al suolo nella posizione corrente del dispositivo e punta verso il geomagnetico Polo Nord.
  • Z è rivolto verso il cielo ed è perpendicolare al piano di suolo.

Per un'applicazione di esempio che mostra come utilizzare il sensore del vettore di rotazione, consulta RotazioneVectorDemo.java.

Usa il sensore di movimento significativo

Il sensore di movimento significativo attiva un evento ogni volta che viene rilevato un movimento significativo. poi si disattiva. Un movimento significativo è un movimento che potrebbe portare a un cambiamento nella la località dell'utente; ad esempio a piedi, in bicicletta o seduto su un'auto in movimento. Il seguente codice mostra come ottenere un'istanza del sensore di movimento significativo predefinito e come registrare un evento listener:

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

Per ulteriori informazioni, vedi TriggerEventListener.

Uso del sensore contapassi

Il sensore del contatore di passi fornisce il numero di passi effettuati dall'utente dall'ultimo riavvio mentre il sensore era attivato. Il contapassi ha più latenza (fino a 10 secondi), ma più più precisa rispetto al sensore del rilevatore di passi.

Nota : devi dichiarare il ACTIVITY_RECOGNITION: autorizzazione per consentire alla tua app di usare questo sensore sui dispositivi con Android 10 (livello API 29) o versioni successive.

Il codice seguente mostra come ottenere un'istanza del passaggio predefinito sensore contatore:

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

Per risparmiare batteria sui dispositivi che eseguono la tua app, devi usare la JobScheduler classe da cui recuperare il valore corrente sensore contapassi a un intervallo specifico. Sebbene diversi tipi di app richiedono intervalli di lettura del sensore diversi, devi impostare questo intervallo come più a lungo possibile, a meno che la tua app non richieda dati in tempo reale dal sensore.

Utilizzare il sensore del rilevatore di passi

Il sensore del rilevatore di passi attiva un evento ogni volta che l'utente fa un passo. La latenza dovrebbe essere inferiore a 2 secondi.

Nota : devi dichiarare il ACTIVITY_RECOGNITION: autorizzazione per consentire alla tua app di usare questo sensore sui dispositivi con Android 10 (livello API 29) o versioni successive.

Il codice seguente mostra come ottenere un'istanza del passaggio predefinito sensore rilevatore:

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

Lavora con dati non elaborati

I seguenti sensori forniscono alla tua app dati non elaborati relativi ai modelli forze di rotazione applicate al dispositivo. Per utilizzare i valori questi sensori in modo efficace, è necessario filtrare i fattori ambientali, come la gravità. Potresti anche dover applicare un algoritmo di smoothing alla tendenza. di valori per ridurre il rumore.

Usare l'accelerometro

Un sensore di accelerazione misura l'accelerazione applicata al dispositivo, inclusa la forza di gravità. Il seguente codice mostra come ottenere un'istanza del sensore di accelerazione predefinito:

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: se la tua app ha come target Android 12 (livello API 31) o più in alto, il sensore con limitazioni di frequenza.

Concettualmente, un sensore di accelerazione determina l'accelerazione applicata a un dispositivo (Ad) misurando le forze applicate al sensore (Fs) utilizzando la seguente relazione:

A_D=-(1/massa)ΣF_S

Tuttavia, la forza di gravità influenza sempre l'accelerazione misurata in base a la seguente relazione:

A_D=-g-(1/massa)ΣF_S

Per questo motivo, quando il dispositivo è appoggiato su un tavolo (e non accelera), il legge una magnitudo g = 9,81 m/s2 dell'accelerometro. Analogamente, quando il dispositivo si trova in caduta libera e, di conseguenza, in rapida accelerazione verso il suolo a 9,81 m/s2, dell'accelerometro legge una grandezza g = 0 m/s2. Di conseguenza, per misurare l'accelerazione reale del dispositivo, il contributo della forza di gravità deve essere rimosso i dati dell'accelerometro. A questo scopo, può essere applicato un filtro passa-alto. Al contrario, un passaggio basso per isolare la forza di gravità. L'esempio seguente mostra come procedere questo:

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:puoi utilizzare molte tecniche diverse per filtrare i dati dei sensori. L'esempio di codice riportato sopra utilizza una semplice costante di filtro (alpha) per creare un filtro passa basso. Questo filtro costante viene ricavata da una costante di tempo (t), che è una rappresentazione approssimativa della latenza il filtro aggiunge agli eventi del sensore e alla frequenza di consegna degli eventi del sensore (dt). Esempio di codice utilizza un valore alpha di 0,8 a scopo dimostrativo. Se utilizzi questo metodo di filtro, potresti dover per scegliere un valore alfa diverso.

Gli accelerometri usano la coordinata del sensore standard . In pratica, ciò significa che quando il dispositivo è sdraiato si applicano le seguenti condizioni su una tabella nel suo orientamento naturale:

  • Se spingi il dispositivo sul lato sinistro (in modo che si sposti verso destra), il valore di accelerazione x è positivo.
  • Se spingi il dispositivo verso il basso (per allontanarlo da te), il valore di accelerazione y è positivo.
  • Se spingi il dispositivo verso il cielo con un'accelerazione di A m/s2, z valore di accelerazione è uguale a A + 9.81, che corrisponde all'accelerazione del dispositivo (+A m/s2) meno la forza di gravità (-9,81 m/s2).
  • Il dispositivo fisso avrà un valore di accelerazione di +9,81, che corrisponde al accelerazione del dispositivo (0 m/s2 meno la forza di gravità, ossia -9,81 m/s2).

In generale, l'accelerometro è un buon sensore da usare per monitorare il movimento del dispositivo. Quasi tutti i cellulari e i tablet Android dispongono di un accelerometro, che utilizza circa 10 volte di alimentazione in meno rispetto agli altri sensori di movimento. Uno svantaggio è che potresti dover implementare filtri passa-basso e passa-alto per eliminare le forze gravitazionali e ridurre il rumore.

Utilizzare il giroscopio

Il giroscopio misura la velocità di rotazione in rad/s intorno a x, y, e asse z. Il seguente codice mostra come ottenere un'istanza del giroscopio predefinito:

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: se la tua app ha come target Android 12 (livello API 31) o più in alto, il sensore con limitazioni di frequenza.

Il sistema di coordinate del sensore è lo stesso utilizzato per il sensore di accelerazione. La rotazione è positiva in in senso antiorario; cioè un osservatore che guarda da una posizione positiva sull'asse x, y o z in corrispondenza di un dispositivo posizionato sull'origine, il report rotazione positiva se il dispositivo sembra ruotare in senso antiorario. Questo è il definizione matematica standard di rotazione positiva e non corrisponde alla definizione di rotolo utilizzato dal sensore di orientamento.

Di solito, l'output del giroscopio è integrato nel tempo per calcolare una rotazione il cambiamento degli angoli nel passo temporale. Ad esempio:

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

I giroscopi standard forniscono dati rotazionali non elaborati senza filtri o correzioni per il rumore e deviazione (bias). In pratica, il rumore e la deviazione del giroscopio introdurranno errori che devono essere compensato. Di solito determinare la deviazione (bias) e il rumore monitorando altri sensori, come sensore di gravità o accelerometro.

Utilizzare il giroscopio non calibrato

Il giroscopio non calibrato è simile al giroscopio, tranne che al tasso di rotazione non viene applicata alcuna compensazione di deviazione giroscopica. Calibrazione di fabbrica e la compensazione della temperatura sono comunque applicate alla velocità di rotazione. I valori non calibrati il giroscopio è utile per la post-elaborazione e la fusione dei dati di orientamento. In generale, gyroscope_event.values[0] sarà vicino a uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3]. Vale a dire che

calibrated_x ~= uncalibrated_x - bias_estimate_x

Nota:i sensori non calibrati forniscono più risultati non elaborati e potrebbero includono alcuni bias, ma le loro misurazioni contengono meno salti rispetto alle correzioni applicate calibrazione. Alcune applicazioni potrebbero preferire questi risultati non calibrati in quanto più fluidi e più affidabile. Ad esempio, se un'applicazione tenta di condurre la propria fusione dei sensori, le calibrazioni possono effettivamente distorcere i risultati.

Oltre alle velocità di rotazione, il giroscopio non calibrato fornisce anche la stima o una deviazione attorno a ciascun asse. Il seguente codice mostra come ottenere un'istanza del cluster giroscopio non calibrato:

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

Altri esempi di codice

La L'esempio BatchStepSensor illustra ulteriormente l'uso delle API trattate in questa pagina.

Dovresti leggere inoltre