La piattaforma Android fornisce due sensori che ti consentono di determinare la posizione di un dispositivo: il sensore del campo geomagnetico e l'accelerometro. Android della piattaforma fornisce anche un sensore che consente di determinare la distanza dal viso di un dispositivo è a un oggetto (noto come sensore di prossimità). La il sensore di campo geomagnetico e il sensore di prossimità sono basati su hardware. Più alta i produttori di smartphone e tablet includono un sensore di campo geomagnetico. Analogamente, di solito includono un sensore di prossimità per determinare quando un lo smartphone viene tenuto vicino al viso di un utente (ad esempio, durante uno smartphone chiamata). Per determinare l'orientamento di un dispositivo, puoi utilizzare le letture da l'accelerometro del dispositivo e il sensore del campo geomagnetico.
Nota:il sensore di orientamento è stato ritirato in Android 2.2 (livello API 8) e il tipo di sensore di orientamento è stato ritirato su Android 4.4W (livello API 20).
I sensori di posizione sono utili per determinare la posizione fisica di un dispositivo il quadro di riferimento globale. Ad esempio, puoi utilizzare il campo geomagnetico sensore in combinazione con l'accelerometro per determinare la posizione di un dispositivo rispetto al polo nord magnetico. Puoi usare questi sensori anche per Stabilire l'orientamento di un dispositivo nel contesto di riferimento della tua applicazione. In genere i sensori di posizione non vengono utilizzati per monitorare i movimenti o i movimenti del dispositivo, ad esempio oscillazione, inclinazione o spinta (per ulteriori informazioni, consulta la sezione Sensori di movimento).
Il sensore del campo geomagnetico e l'accelerometro restituiscono array multidimensionali
di valori del sensore per ogni SensorEvent
. Ad esempio:
il sensore di campo geomagnetico fornisce valori di intensità del campo geomagnetico per
per ognuno dei tre assi di coordinate durante un singolo evento del sensore. Analogamente,
del sensore dell'accelerometro misura l'accelerazione applicata al dispositivo durante un
un evento del sensore. Per ulteriori informazioni sui sistemi di coordinate utilizzati
tramite i sensori, vedi
Sistemi di coordinate dei sensori. Il sensore di prossimità fornisce un singolo valore
per ciascun evento del sensore. La tabella 1 riassume i sensori di posizione
supportate dalla piattaforma Android.
Tabella 1. Sensori di posizione supportati dalla piattaforma Android.
Sensore | Dati sugli eventi dei sensori | Descrizione | Unità di misura |
---|---|---|---|
TYPE_GAME_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)). | ||
TYPE_GEOMAGNETIC_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)). | ||
TYPE_MAGNETIC_FIELD |
SensorEvent.values[0] |
Intensità del campo geomagnetico lungo l'asse x. | μT |
SensorEvent.values[1] |
Intensità del campo geomagnetico lungo l'asse y. | ||
SensorEvent.values[2] |
Intensità del campo geomagnetico lungo l'asse z. | ||
TYPE_MAGNETIC_FIELD_UNCALIBRATED |
SensorEvent.values[0] |
Intensità del campo geomagnetico (senza calibrazione del ferro duro) lungo l'asse x. | μT |
SensorEvent.values[1] |
Intensità del campo geomagnetico (senza calibrazione del ferro duro) lungo l'asse y. | ||
SensorEvent.values[2] |
Intensità del campo geomagnetico (senza calibrazione del ferro duro) lungo l'asse z. | ||
SensorEvent.values[3] |
Stima della differenziazione del ferro lungo l'asse x. | ||
SensorEvent.values[4] |
Stima della differenziazione del ferro lungo l'asse y. | ||
SensorEvent.values[5] |
Stima della differenziazione del ferro lungo l'asse z. | ||
TYPE_ORIENTATION 1 |
SensorEvent.values[0] |
Azimut (angolo intorno all'asse z). | Gradi |
SensorEvent.values[1] |
Angolo (angolo intorno all'asse x). | ||
SensorEvent.values[2] |
Rotazione (angolo intorno all'asse y). | ||
TYPE_PROXIMITY |
SensorEvent.values[0] |
Distanza dall'oggetto.2 | cm |
1Questo sensore è stato ritirato in Android 2.2 (API livello 8) e questo tipo di sensore è stato deprecato in Android 4.4W (livello API 20). La struttura dei sensori fornisce metodi alternativi per l'acquisizione del dispositivo di cui parleremo in Computing l'orientamento del dispositivo.
2 Alcuni sensori di prossimità forniscono solo valori binari che rappresentano il vicino e il lontano.
Usa il sensore vettoriale di rotazione del gioco
Il sensore del vettore di rotazione del gioco è identico Rotazione vettoriale, ma non utilizza il campo geomagnetico. Di conseguenza, l'asse Y non puntare a nord e non a un altro riferimento. Tale riferimento può variare stesso ordine di grandezza di quello del giroscopio che devia lungo l'asse Z.
Poiché il sensore di vettore di rotazione del gioco non utilizza il campo magnetico, le rotazioni relative sono più precisi e non influenzati dalle variazioni del campo magnetico. Usa questo sensore in un gioco se non ti interessa dove si trova il nord e il normale vettore di rotazione non soddisfa le tue esigenze a causa della sua dipendenza dal campo magnetico.
Il seguente codice mostra come ottenere un'istanza del vettore di rotazione predefinito del gioco sensore:
Kotlin
private lateinit var sensorManager: SensorManager private var sensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
Utilizza il sensore vettoriale di rotazione geomagnetica
Il sensore vettoriale di rotazione geomagnetica è simile al sensore vettoriale di rotazione, non usa il giroscopio. La precisione di questo sensore è inferiore al normale vettore di rotazione. sensore, ma il consumo di corrente è ridotto. Usa questo sensore solo se vuoi acquisire la rotazione le informazioni in background senza consumare troppa batteria. Questo sensore è utile soprattutto quando in combinazione con la creazione in batch.
Il seguente codice mostra come ottenere un'istanza della rotazione geomagnetica predefinita sensore vettoriale:
Kotlin
private lateinit var sensorManager: SensorManager private var sensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);
Calcola l'orientamento del dispositivo
Calcolando l'orientamento di un dispositivo, puoi monitorare la posizione dispositivo rispetto al quadro di riferimento della Terra (in particolare, il sensore magnetico polo nord). Il seguente codice mostra come calcolare il numero orientamento:
Kotlin
private lateinit var sensorManager: SensorManager ... // Rotation matrix based on current readings from accelerometer and magnetometer. val rotationMatrix = FloatArray(9) SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading) // Express the updated rotation matrix as three orientation angles. val orientationAngles = FloatArray(3) SensorManager.getOrientation(rotationMatrix, orientationAngles)
Java
private SensorManager sensorManager; ... // Rotation matrix based on current readings from accelerometer and magnetometer. final float[] rotationMatrix = new float[9]; SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading); // Express the updated rotation matrix as three orientation angles. final float[] orientationAngles = new float[3]; SensorManager.getOrientation(rotationMatrix, orientationAngles);
Il sistema calcola gli angoli di orientamento utilizzando la tecnologia geomagnetica di un dispositivo sensore di campo in combinazione con l'accelerometro del dispositivo. Usando questi due strumenti, sensori hardware hardware, il sistema fornisce i dati per i tre seguenti angoli di orientamento:
- Azimut (gradi di rotazione attorno all'asse -z). Questo è l'angolo tra la direzione attuale della bussola del dispositivo e il nord magnetico. Se il bordo superiore del dispositivo è rivolto verso il nord magnetico, l'azimut è 0. gradi; se il bordo superiore è rivolto a sud, l'azimut è di 180 gradi. Analogamente, se il bordo superiore è rivolto a est, l'azimut è di 90 gradi e se il bordo superiore è rivolto a ovest, con l'azimut di 270 gradi.
- Angolazione (gradi di rotazione intorno all'asse x). Questo è il angolo tra un piano parallelo allo schermo del dispositivo e un piano parallelo a terra. Se tieni il dispositivo parallelo al suolo con la parte inferiore bordo più vicino a te e inclina il bordo superiore del dispositivo verso il suolo l'angolo d'inclinazione diventa positivo. Inclinazione nella direzione opposta: Sposta il bordo superiore del dispositivo lontano da terra; l'angolo di inclinazione per diventare negativo. L'intervallo di valori va da -90 gradi a 90 gradi.
- Rotazione (gradi di rotazione attorno all'asse y). Questo è il angolo tra un piano perpendicolare allo schermo del dispositivo e un piano perpendicolare al suolo. Se tieni il dispositivo parallelo al suolo con il bordo inferiore più vicino a te e inclina il bordo sinistro del dispositivo verso il suolo, l'angolo di rotazione diventa positivo. Inclinazione al contrario (spostando il bordo destro del dispositivo verso il suolo) fa sì che l'angolo di rotazione diventi negativo. L'intervallo di valori è -180 gradi fino a 180 gradi.
Nota: la definizione del rullo del sensore è stata modificata per riflettere la la maggior parte delle implementazioni nell'ecosistema dei geosensori.
Tieni presente che questi angoli funzionano a partire da un sistema di coordinate diverso rispetto quella usata nell'aviazione (per imbarcazione, beccheggio e lancio). Nel sistema aeronautico, l'asse x si trova lungo il lato lungo del piano, dalla coda al naso.
Il sensore di orientamento ricava i dati elaborando i dati non elaborati del sensore
dall'accelerometro e dal sensore del campo geomagnetico. A causa dell'intensa
l'accuratezza e la precisione dell'orientamento
il sensore diminuisce. Nello specifico, questo sensore è affidabile solo
è 0. Di conseguenza, il sensore di orientamento è stato ritirato in Android
2.2 (livello API 8) e il tipo di sensore di orientamento è stato ritirato su Android
4,4 W (livello API 20).
Anziché utilizzare dati non elaborati provenienti dal sensore di orientamento, ti consigliamo
usa getRotationMatrix()
in combinazione con
Metodo getOrientation()
per calcolare i valori di orientamento, come mostrato nel seguente esempio di codice. Nell'ambito
di questa procedura, puoi utilizzare
remapCoordinateSystem()
per tradurre i valori di orientamento nel frame dell'applicazione di
riferimento.
Kotlin
class SensorActivity : Activity(), SensorEventListener { private lateinit var sensorManager: SensorManager private val accelerometerReading = FloatArray(3) private val magnetometerReading = FloatArray(3) private val rotationMatrix = FloatArray(9) private val orientationAngles = FloatArray(3) public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) { // Do something here if sensor accuracy changes. // You must implement this callback in your code. } override fun onResume() { super.onResume() // Get updates from the accelerometer and magnetometer at a constant rate. // To make batch operations more efficient and reduce power consumption, // provide support for delaying updates to the application. // // In this example, the sensor reporting delay is small enough such that // the application receives an update before the system checks the sensor // readings again. sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)?.also { accelerometer -> sensorManager.registerListener( this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI ) } sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also { magneticField -> sensorManager.registerListener( this, magneticField, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI ) } } override fun onPause() { super.onPause() // Don't receive any more updates from either sensor. sensorManager.unregisterListener(this) } // Get readings from accelerometer and magnetometer. To simplify calculations, // consider storing these readings as unit vectors. override fun onSensorChanged(event: SensorEvent) { if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) { System.arraycopy(event.values, 0, accelerometerReading, 0, accelerometerReading.size) } else if (event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) { System.arraycopy(event.values, 0, magnetometerReading, 0, magnetometerReading.size) } } // Compute the three orientation angles based on the most recent readings from // the device's accelerometer and magnetometer. fun updateOrientationAngles() { // Update rotation matrix, which is needed to update orientation angles. SensorManager.getRotationMatrix( rotationMatrix, null, accelerometerReading, magnetometerReading ) // "rotationMatrix" now has up-to-date information. SensorManager.getOrientation(rotationMatrix, orientationAngles) // "orientationAngles" now has up-to-date information. } }
Java
public class SensorActivity extends Activity implements SensorEventListener { private SensorManager sensorManager; private final float[] accelerometerReading = new float[3]; private final float[] magnetometerReading = new float[3]; private final float[] rotationMatrix = new float[9]; private final float[] orientationAngles = new float[3]; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // Do something here if sensor accuracy changes. // You must implement this callback in your code. } @Override protected void onResume() { super.onResume(); // Get updates from the accelerometer and magnetometer at a constant rate. // To make batch operations more efficient and reduce power consumption, // provide support for delaying updates to the application. // // In this example, the sensor reporting delay is small enough such that // the application receives an update before the system checks the sensor // readings again. Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (accelerometer != null) { sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI); } Sensor magneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); if (magneticField != null) { sensorManager.registerListener(this, magneticField, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI); } } @Override protected void onPause() { super.onPause(); // Don't receive any more updates from either sensor. sensorManager.unregisterListener(this); } // Get readings from accelerometer and magnetometer. To simplify calculations, // consider storing these readings as unit vectors. @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { System.arraycopy(event.values, 0, accelerometerReading, 0, accelerometerReading.length); } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { System.arraycopy(event.values, 0, magnetometerReading, 0, magnetometerReading.length); } } // Compute the three orientation angles based on the most recent readings from // the device's accelerometer and magnetometer. public void updateOrientationAngles() { // Update rotation matrix, which is needed to update orientation angles. SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading); // "rotationMatrix" now has up-to-date information. SensorManager.getOrientation(rotationMatrix, orientationAngles); // "orientationAngles" now has up-to-date information. } }
Di solito non è necessario eseguire l'elaborazione dei dati o l'applicazione di filtri al angoli di orientamento non elaborati del dispositivo, diversi dalla traduzione del sensore di coordinamento al frame di riferimento dell'applicazione.
Utilizzare il sensore di campo geomagnetico
Il sensore di campo geomagnetico ti consente di monitorare le variazioni del campo magnetico terrestre. La Il seguente codice mostra come ottenere un'istanza del sensore di campo geomagnetico predefinito:
Kotlin
private lateinit var sensorManager: SensorManager private var sensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
Nota: se la tua app ha come target Android 12 (livello API 31) o più in alto, il sensore con limitazioni di frequenza.
Questo sensore fornisce i dati non elaborati sull'intensità di campo (in μT) per ciascuno dei tre assi di coordinate.
In genere, non è necessario utilizzare direttamente questo sensore. Al contrario, puoi utilizzare il vettore di rotazione
sensore per determinare il movimento rotatorio non elaborato oppure puoi utilizzare l'accelerometro e il campo geomagnetico
sensore in combinazione con il metodo getRotationMatrix()
per ottenere la matrice di rotazione e la matrice di inclinazione. Puoi quindi
usa queste matrici con getOrientation()
e getInclination()
per ottenere l'azimut
e dati di inclinazione geomagnetica.
Nota : quando testi la tua app, puoi migliorare la precisione del sensore agitando il dispositivo secondo una sequenza a 8.
Utilizza il magnetometro non calibrato
Il magnetometro non calibrato è simile al campo geomagnetico
sensore, ma non viene applicata alcuna calibrazione di ferro duro al campo magnetico. Calibrazione di fabbrica
e la compensazione della temperatura
sono ancora applicate al campo magnetico. Il magnetometro non calibrato
è utile per gestire stime errate del ferro duro. In generale, geomagneticsensor_event.values[0]
sarà vicino a uncalibrated_magnetometer_event.values[0] -
uncalibrated_magnetometer_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 al campo magnetico, il magnetometro non calibrato fornisce anche bias stimato del ferro duro su ogni asse. Il seguente codice mostra come ottenere un'istanza del magnetometro non calibrato predefinito:
Kotlin
private lateinit var sensorManager: SensorManager private var sensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);
Utilizzare il sensore di prossimità
Il sensore di prossimità consente di determinare la distanza di un oggetto da un dispositivo. Le seguenti mostra come ottenere un'istanza del sensore di prossimità predefinito:
Kotlin
private lateinit var sensorManager: SensorManager private var sensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
Il sensore di prossimità viene solitamente utilizzato per determinare la distanza della testa di una persona dal viso di uno smartphone (ad esempio, quando un utente effettua o riceve una chiamata). Più alta i sensori di prossimità restituiscono la distanza assoluta, in cm, ma alcuni ritornano solo vicino e valori lontani.
Nota: su alcuni modelli di dispositivi, il sensore di prossimità si trova sotto lo schermo; in questo modo, è possibile che appaia un pallino lampeggiante se questa impostazione è attiva mentre lo schermo è attiva.
Il seguente codice mostra come utilizzare il sensore di prossimità:
Kotlin
class SensorActivity : Activity(), SensorEventListener { private lateinit var sensorManager: SensorManager private var proximity: Sensor? = null public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) // Get an instance of the sensor service, and use that to get an instance of // a particular sensor. sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) { // Do something here if sensor accuracy changes. } override fun onSensorChanged(event: SensorEvent) { val distance = event.values[0] // Do something with this sensor data. } override fun onResume() { // Register a listener for the sensor. super.onResume() proximity?.also { proximity -> sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL) } } override fun onPause() { // Be sure to unregister the sensor when the activity pauses. super.onPause() sensorManager.unregisterListener(this) } }
Java
public class SensorActivity extends Activity implements SensorEventListener { private SensorManager sensorManager; private Sensor proximity; @Override public final void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Get an instance of the sensor service, and use that to get an instance of // a particular sensor. sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); } @Override public final void onAccuracyChanged(Sensor sensor, int accuracy) { // Do something here if sensor accuracy changes. } @Override public final void onSensorChanged(SensorEvent event) { float distance = event.values[0]; // Do something with this sensor data. } @Override protected void onResume() { // Register a listener for the sensor. super.onResume(); sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onPause() { // Be sure to unregister the sensor when the activity pauses. super.onPause(); sensorManager.unregisterListener(this); } }
Nota: alcuni sensori di prossimità restituiscono valori binari che rappresentano
"vicino" o "lontano". In questo caso, il sensore di solito riporta il valore massimo dell'intervallo nello stato lontano
e un valore minore nello stato vicino. Di solito, il valore lontano è un valore > 5 cm, ma questo valore può variare
da un sensore all'altro. Puoi determinare la portata massima di un sensore usando il metodo getMaximumRange()
.