Utilizza l'API Generic Sensor per accedere ai sensori sul dispositivo, come accelerometri, giroscopi e magnetometri.
Oggi, i dati dei sensori vengono utilizzati in molte applicazioni specifiche della piattaforma per consentire casi d'uso come giochi immersivi, monitoraggio dell'attività fisica e realtà aumentata o virtuale. Non sarebbe fantastico colmare il divario tra le applicazioni specifiche per piattaforma e quelle web? Inserisci l'API Generic Sensor per il web.
Che cos'è l'API Generic Sensor?
L'API Generic Sensor è un insieme di interfacce che espongono
i dispositivi sensore alla piattaforma web. L'API è costituita dall'interfaccia di base
Sensor e da un insieme di classi di sensori
concrete create al di sopra. La presenza di un'interfaccia di base semplifica l'implementazione e la specifica
per le classi di sensori concrete. Ad esempio, dai un'occhiata alla classe
Gyroscope. È piccolissimo. La funzionalità
principale è specificata dall'interfaccia di base e Gyroscope la estende semplicemente con tre
attributi che rappresentano la velocità angolare.
Alcune classi di sensori interagiscono con sensori hardware reali, ad esempio le classi di accelerometro o
giroscopio. Questi sono chiamati sensori di basso livello. Altri sensori, chiamati sensori di fusione, uniscono i dati di diversi sensori di basso livello per esporre informazioni che altrimenti uno script dovrebbe calcolare. Ad esempio, il
sensore AbsoluteOrientation
fornisce una matrice di rotazione 4x4 pronta all'uso basata sui dati ottenuti da
accelerometro, giroscopio e magnetometro.
Potresti pensare che la piattaforma web fornisca già dati dei sensori e hai assolutamente ragione. Ad esempio, gli eventi DeviceMotion e DeviceOrientation espongono i dati del sensore di movimento. Allora perché abbiamo bisogno di una nuova API?
Rispetto alle interfacce esistenti, l'API Generic Sensor offre numerosi vantaggi:
- L'API Generic Sensor è un framework di sensori che può essere facilmente esteso con nuove classi di sensori e ognuna di queste classi manterrà l'interfaccia generica. Il codice client scritto per un tipo di sensore può essere riutilizzato per un altro con pochissime modifiche.
- Puoi configurare il sensore. Ad esempio, puoi impostare la frequenza di campionamento adatta alle esigenze della tua applicazione.
- Puoi rilevare se un sensore è disponibile sulla piattaforma.
- Le letture dei sensori hanno timestamp di alta precisione, il che consente una migliore sincronizzazione con altre attività nella tua applicazione.
- I modelli di dati dei sensori e i sistemi di coordinate sono definiti in modo chiaro, consentendo ai fornitori di browser di implementare soluzioni interoperabili.
- Le interfacce basate su sensori generici non sono associate al DOM (ovvero non sono oggetti
navigatornéwindow) e ciò apre future opportunità per l'utilizzo dell'API all'interno dei service worker o per la sua implementazione in runtime JavaScript headless, come i dispositivi incorporati. - Gli aspetti di sicurezza e privacy sono la massima priorità per l'API Generic Sensor e offrono una sicurezza molto migliore rispetto alle API dei sensori precedenti. Esiste un'integrazione con l'API Permissions.
- La sincronizzazione automatica con le coordinate dello schermo è
disponibile per
Accelerometer,Gyroscope,LinearAccelerationSensor,AbsoluteOrientationSensor,RelativeOrientationSensoreMagnetometer.
API per sensori generici disponibili
Al momento della stesura, sono disponibili diversi sensori con cui puoi sperimentare.
Sensori di movimento:
AccelerometerGyroscopeLinearAccelerationSensorAbsoluteOrientationSensorRelativeOrientationSensorGravitySensor
Sensori ambientali:
AmbientLightSensor(Dietro il flag#enable-generic-sensor-extra-classesin Chromium).Magnetometer(Dietro il flag#enable-generic-sensor-extra-classesin Chromium).
Rilevamento delle funzionalità
Il rilevamento delle funzionalità delle API hardware è complicato, in quanto devi rilevare sia se il browser
supporta l'interfaccia in questione sia se il dispositivo dispone del sensore corrispondente. Verificare
se il browser supporta un'interfaccia è semplice. Sostituisci Accelerometer con una delle altre interfacce menzionate sopra.
if ('Accelerometer' in window) {
// The `Accelerometer` interface is supported by the browser.
// Does the device have an accelerometer, though?
}
Per un risultato di rilevamento delle funzionalità effettivamente significativo, devi provare a connetterti anche al sensore. Questo esempio illustra come farlo.
let accelerometer = null;
try {
accelerometer = new Accelerometer({ frequency: 10 });
accelerometer.onerror = (event) => {
// Handle runtime errors.
if (event.error.name === 'NotAllowedError') {
console.log('Permission to access sensor was denied.');
} else if (event.error.name === 'NotReadableError') {
console.log('Cannot connect to the sensor.');
}
};
accelerometer.onreading = (e) => {
console.log(e);
};
accelerometer.start();
} catch (error) {
// Handle construction errors.
if (error.name === 'SecurityError') {
console.log('Sensor construction was blocked by the Permissions Policy.');
} else if (error.name === 'ReferenceError') {
console.log('Sensor is not supported by the User Agent.');
} else {
throw error;
}
}
Polyfill
Per i browser che non supportano l'API Generic Sensor, è disponibile un polyfill. Il polyfill ti consente di caricare solo le implementazioni dei sensori pertinenti.
// Import the objects you need.
import { Gyroscope, AbsoluteOrientationSensor } from './src/motion-sensors.js';
// And they're ready for use!
const gyroscope = new Gyroscope({ frequency: 15 });
const orientation = new AbsoluteOrientationSensor({ frequency: 60 });
Cosa sono tutti questi sensori? Come posso utilizzarli?
I sensori sono un'area che potrebbe richiedere una breve introduzione. Se hai familiarità con i sensori, puoi andare direttamente alla sezione di programmazione pratica. Altrimenti, esaminiamo nel dettaglio ogni sensore supportato.
Accelerometro e sensore di accelerazione lineare
Il sensore Accelerometer
misura l'accelerazione di un dispositivo che ospita il sensore su tre assi (X, Y e Z). Questo sensore è un
sensore inerziale, il che significa che quando il dispositivo è in caduta libera lineare, l'accelerazione totale misurata
sarebbe 0 m/s2 e quando un dispositivo è appoggiato su un tavolo, l'accelerazione
in direzione verso l'alto (asse Z) sarà uguale alla gravità terrestre, ovvero g ≈ +9,8 m/s2, in quanto
misura la forza del tavolo che spinge il dispositivo verso l'alto. Se spingi il dispositivo verso
destra, l'accelerazione sull'asse X sarà positiva, o negativa se il dispositivo viene accelerato da
destra verso sinistra.
Gli accelerometri possono essere utilizzati per attività come il conteggio dei passi, il rilevamento del movimento o il semplice orientamento del dispositivo. Molto spesso, le misurazioni dell'accelerometro vengono combinate con i dati di altre origini per creare sensori di fusione, ad esempio i sensori di orientamento.
L'LinearAccelerationSensor misura l'accelerazione applicata al dispositivo che ospita il sensore, escluso il contributo della gravità. Quando un dispositivo è a riposo, ad esempio appoggiato su un tavolo, il sensore misurerebbe
un'accelerazione di ≈ 0 m/s2 su tre assi.
Sensore di gravità
Gli utenti possono già derivare manualmente letture vicine a quelle di un sensore di gravità
ispezionando manualmente le letture di Accelerometer e LinearAccelerometer, ma questa operazione può essere complessa
e dipende dalla precisione dei valori forniti da questi sensori. Piattaforme come Android possono
fornire letture della gravità come parte del sistema operativo, il che dovrebbe essere più economico in termini di
calcolo, fornire valori più accurati a seconda dell'hardware dell'utente ed essere più facile da usare in
termini di ergonomia dell'API. GravitySensor restituisce l'effetto dell'accelerazione lungo gli assi X, Y e Z del dispositivo dovuta alla gravità.
Giroscopio
Il sensore Gyroscope misura
la velocità angolare in radianti al secondo attorno agli assi X, Y e Z locali del dispositivo. La maggior parte dei dispositivi
di consumo è dotata di giroscopi meccanici (MEMS),
che sono sensori inerziali che misurano la velocità di rotazione in base alla
forza di Coriolis inerziale. I giroscopi MEMS sono soggetti
a deriva causata dalla sensibilità alla gravità del sensore, che deforma il sistema
meccanico interno del sensore. I giroscopi oscillano a frequenze relativamente elevate, ad esempio: decine di kHz e, pertanto, potrebbe consumare più energia rispetto ad altri sensori.
Sensori di orientamento
Il
AbsoluteOrientationSensor
è un sensore di fusione che misura la rotazione di un dispositivo rispetto al sistema di coordinate della Terra,
mentre
RelativeOrientationSensor
fornisce dati che rappresentano la rotazione di un dispositivo che ospita sensori di movimento rispetto a un sistema di coordinate di riferimento
fisso.
Tutti i framework JavaScript 3D moderni supportano i quaternioni e le matrici di rotazione per rappresentare la rotazione. Tuttavia, se utilizzi direttamente WebGL, OrientationSensor dispone comodamente sia di una proprietà quaternion sia di un metodo populateMatrix().
Ecco alcuni snippet:
let torusGeometry = new THREE.TorusGeometry(7, 1.6, 4, 3, 6.3);
let material = new THREE.MeshBasicMaterial({ color: 0x0071c5 });
let torus = new THREE.Mesh(torusGeometry, material);
scene.add(torus);
// Update mesh rotation using quaternion.
const sensorAbs = new AbsoluteOrientationSensor();
sensorAbs.onreading = () => torus.quaternion.fromArray(sensorAbs.quaternion);
sensorAbs.start();
// Update mesh rotation using rotation matrix.
const sensorRel = new RelativeOrientationSensor();
let rotationMatrix = new Float32Array(16);
sensor_rel.onreading = () => {
sensorRel.populateMatrix(rotationMatrix);
torus.matrix.fromArray(rotationMatrix);
};
sensorRel.start();
const mesh = new BABYLON.Mesh.CreateCylinder('mesh', 0.9, 0.3, 0.6, 9, 1, scene);
const sensorRel = new RelativeOrientationSensor({ frequency: 30 });
sensorRel.onreading = () => mesh.rotationQuaternion.FromArray(sensorRel.quaternion);
sensorRel.start();
// Initialize sensor and update model matrix when new reading is available.
let modMatrix = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
const sensorAbs = new AbsoluteOrientationSensor({ frequency: 60 });
sensorAbs.onreading = () => sensorAbs.populateMatrix(modMatrix);
sensorAbs.start();
// Somewhere in rendering code, update vertex shader attribute for the model
gl.uniformMatrix4fv(modMatrixAttr, false, modMatrix);
I sensori di orientamento consentono vari casi d'uso, come giochi immersivi, realtà aumentata e virtuale.
Per saperne di più su sensori di movimento, casi d'uso avanzati e requisiti, consulta il documento Spiegazione dei sensori di movimento.
Sincronizzazione con le coordinate dello schermo
Per impostazione predefinita, le letture dei sensori spaziali vengono risolte in un sistema di coordinate locale associato al dispositivo e non tengono conto dell'orientamento dello schermo.
Tuttavia, molti casi d'uso come giochi o realtà aumentata e virtuale richiedono che le letture dei sensori vengano risolte in un sistema di coordinate vincolato all'orientamento dello schermo.
In precedenza, la rimappatura delle letture dei sensori alle coordinate dello schermo doveva essere implementata in JavaScript. Questo approccio è inefficiente e aumenta in modo significativo la complessità del codice dell'applicazione web; l'applicazione web deve monitorare i cambiamenti di orientamento dello schermo ed eseguire trasformazioni delle coordinate per le letture dei sensori, il che non è una cosa banale da fare per gli angoli di Eulero o i quaternioni.
L'API Generic Sensor fornisce una soluzione molto più semplice e affidabile. Il sistema di coordinate locale è
configurabile per tutte le classi di sensori spaziali definite: Accelerometer, Gyroscope,
LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensor e
Magnetometer. Passando l'opzione referenceFrame al costruttore dell'oggetto sensore, l'utente
definisce se le letture restituite verranno risolte in
coordinate dispositivo o
schermo.
// Sensor readings are resolved in the Device coordinate system by default.
// Alternatively, could be RelativeOrientationSensor({referenceFrame: "device"}).
const sensorRelDevice = new RelativeOrientationSensor();
// Sensor readings are resolved in the Screen coordinate system. No manual remapping is required!
const sensorRelScreen = new RelativeOrientationSensor({ referenceFrame: 'screen' });
Iniziamo a programmare.
L'API Generic Sensor è molto semplice e facile da usare. L'interfaccia del sensore dispone di metodi
start() e
stop() per controllare lo stato del sensore e di diversi
gestori di eventi per ricevere notifiche relative all'attivazione del sensore, agli errori e alle letture
appena disponibili. Le classi di sensori concreti di solito aggiungono i loro attributi di lettura specifici alla classe
di base.
Ambiente di sviluppo
Durante lo sviluppo potrai utilizzare i sensori tramite localhost. Se sviluppi per
dispositivi mobili, configura
il port forwarding
per il tuo server locale e sei pronto per iniziare.
Quando il codice è pronto, esegui il deployment su un server che supporta il protocollo HTTPS. GitHub Pages vengono pubblicate tramite HTTPS, il che le rende un ottimo posto per condividere le tue demo.
Rotazione del modello 3D
In questo semplice esempio, utilizziamo i dati di un sensore di orientamento assoluto per modificare il quaternione di rotazione di un modello 3D. model è un'istanza di classe
Object3D three.js con una proprietà
quaternion. Il
seguente snippet di codice della
demo orientation phone
mostra come il sensore di orientamento assoluto può essere utilizzato per ruotare un modello 3D.
function initSensor() {
sensor = new AbsoluteOrientationSensor({ frequency: 60 });
sensor.onreading = () => model.quaternion.fromArray(sensor.quaternion);
sensor.onerror = (event) => {
if (event.error.name == 'NotReadableError') {
console.log('Sensor is not available.');
}
};
sensor.start();
}
L'orientamento del dispositivo si rifletterà nella rotazione 3D di model all'interno della scena WebGL.
Punchmeter
Il seguente snippet di codice è estratto dalla demo di punchmeter, che mostra come il sensore di accelerazione lineare può essere utilizzato per calcolare la velocità massima di un dispositivo presupponendo che sia inizialmente fermo.
this.maxSpeed = 0;
this.vx = 0;
this.ax = 0;
this.t = 0;
/* … */
this.accel.onreading = () => {
let dt = (this.accel.timestamp - this.t) * 0.001; // In seconds.
this.vx += ((this.accel.x + this.ax) / 2) * dt;
let speed = Math.abs(this.vx);
if (this.maxSpeed < speed) {
this.maxSpeed = speed;
}
this.t = this.accel.timestamp;
this.ax = this.accel.x;
};
La velocità attuale viene calcolata come approssimazione dell'integrale della funzione di accelerazione.
Debug ed override dei sensori con Chrome DevTools
In alcuni casi non è necessario un dispositivo fisico per utilizzare l'API Generic Sensor. Chrome DevTools supporta la simulazione dell'orientamento del dispositivo.
Privacy e sicurezza
Le letture dei sensori sono dati sensibili che possono essere soggetti a vari attacchi da pagine web dannose. Le implementazioni delle API Generic Sensor applicano alcune limitazioni per ridurre i possibili rischi per la sicurezza e la privacy. Queste limitazioni devono essere prese in considerazione dagli sviluppatori che intendono utilizzare l'API, quindi elenchiamole brevemente.
Solo HTTPS
Poiché l'API Generic Sensor è una funzionalità potente, il browser la consente solo in contesti sicuri. In pratica, per utilizzare l'API Generic Sensor, devi accedere alla pagina tramite HTTPS. Durante lo sviluppo puoi farlo tramite http://localhost, ma per la produzione dovrai avere HTTPS sul server. Consulta la raccolta Sicurezza e protezione per best practice e linee guida.
Integrazione dei criteri relativi alle autorizzazioni
L'integrazione delle norme relative alle autorizzazioni nell'API Generic Sensor controlla l'accesso ai dati dei sensori per un frame.
Per impostazione predefinita, gli oggetti Sensor possono essere creati solo all'interno di un frame principale o di iframe con la stessa origine,
impedendo così agli iframe multiorigine di leggere i dati dei sensori senza autorizzazione. Questo comportamento predefinito
può essere modificato attivando o disattivando esplicitamente le
funzionalità controllate dai criteri.
Lo snippet riportato di seguito illustra la concessione dell'accesso ai dati dell'accelerometro a un iframe multiorigine, il che significa
che ora è possibile creare oggetti Accelerometer o LinearAccelerationSensor.
<iframe src="https://third-party.com" allow="accelerometer" />
La trasmissione delle letture dei sensori può essere sospesa
Le letture dei sensori sono accessibili solo da una pagina web visibile, ovvero quando l'utente interagisce effettivamente con la pagina. Inoltre, i dati dei sensori non verranno forniti al frame principale se l'utente si concentra su un subframe multiorigine. In questo modo, il frame principale non può dedurre l'input dell'utente.
Passaggi successivi
Esiste un insieme di classi di sensori già specificate da implementare nel prossimo futuro, ad esempio Sensore di luce ambientale o Sensore di prossimità; tuttavia, grazie alla grande estensibilità del framework Generic Sensor, possiamo prevedere la comparsa di nuove classi che rappresentano vari tipi di sensori.
Un altro aspetto importante per il lavoro futuro è il miglioramento dell'API Generic Sensor stessa. La specifica Generic Sensor è attualmente una raccomandazione candidata, il che significa che c'è ancora tempo per apportare correzioni e introdurre nuove funzionalità di cui gli sviluppatori hanno bisogno.
Puoi aiutarci.
Le specifiche dei sensori hanno raggiunto il livello di maturità Consiglio per i candidati, pertanto il feedback degli sviluppatori web e di browser è molto apprezzato. Facci sapere quali funzionalità sarebbe fantastico aggiungere o se c'è qualcosa che vorresti modificare nell'API attuale.
Non esitare a segnalare anche problemi di specifica e bug per l'implementazione di Chrome.
Risorse
- Progetti demo: https://w3c.github.io/generic-sensor-demos/
- Specifica dell'API Generic Sensor: https://w3c.github.io/sensors/
- Problemi con le specifiche: https://github.com/w3c/sensors/issues
- Mailing list del gruppo di lavoro W3C: public-device-apis@w3.org
- Stato della funzionalità di Chrome: https://www.chromestatus.com/feature/5698781827825664
- Bug di implementazione: http://crbug.com?q=component:Blink>Sensor
Ringraziamenti
Questo articolo è stato rivisto da Joe Medley e Kayce Basques.