Sensori per il Web

Utilizza l'API Generic Sensor per accedere ai sensori sul dispositivo come accelerometri, giroscopi e magnetometri.

Alex Shalamov
Alex Shalamov
Mikhail Pozdnyakov
Mikhail Pozdnyakov

Oggi i dati dei sensori vengono utilizzati in molte applicazioni specifiche della piattaforma per abilitare casi d'uso come giochi immersivi, monitoraggio dell'attività fisica e realtà virtuale o aumentata. Non sarebbe fantastico colmare il divario tra le applicazioni web e quelle specifiche della piattaforma? Utilizza l'API Generic Sensor per il web.

Che cos'è l'API Generic Sensor?

L'API Generic Sensor è un insieme di interfacce che espongono sensoriali alla piattaforma web. L'API è composta dalla base Interfaccia di Sensor e una serie di informazioni dei sensori più importanti. Avere un'interfaccia di base semplifica il processo di implementazione e specifica per le classi di sensori concrete. Ad esempio, dai un'occhiata Gyroscope. È minuscolo! La funzionalità di base è specificata dall'interfaccia di base e Gyroscope la estende semplicemente con tre attributi che rappresentano la velocità angolare.

Alcune classi di sensori si interfacciano con sensori hardware reali, ad esempio le classi di accelerometro o giroscopio. In questi casi si parla di sensori di basso livello. Altri sensori, noti come sensori di fusione, consente di unire i dati di diversi livelli per esporre le informazioni che uno script avrebbe altrimenti bisogno di calcolare. Ad esempio, il sensore AbsoluteOrientation fornisce una matrice di rotazione quattro per quattro pronta per l'uso in base ai dati ottenuti dall'accelerometro, dal giroscopio e dal magnetometro.

Si potrebbe pensare che la piattaforma web fornisca già dati dei sensori e tu 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 ciascuna di queste classi manterrà l'interfaccia generica. Il codice client scritto per un tipo di sensore puoi essere riutilizzato per un altro con pochissime modifiche.
  • Puoi configurare il sensore. Ad esempio, puoi impostare la frequenza di campionamento adatta al tuo le esigenze dell'applicazione.
  • Puoi rilevare se sulla piattaforma è disponibile un sensore.
  • Le letture dei sensori hanno timestamp ad alta precisione, che consentono una migliore sincronizzazione con altre attività nella tua applicazione.
  • I modelli dei dati dei sensori e i sistemi di coordinate sono chiaramente definiti, consentendo ai fornitori di browser di implementare soluzioni interoperabili.
  • Le interfacce basate su sensori generici non sono legate al DOM (ovvero non sono oggetti navigator o window), il che apre opportunità future per l'utilizzo dell'API all'interno di service worker o per la sua implementazione in runtime JavaScript headless, come i dispositivi embedded.
  • Gli aspetti relativi a sicurezza e privacy sono la massima priorità per l'API Generic Sensor e offrono una sicurezza molto migliore rispetto alle API di sensori precedenti. È presente l'integrazione con l'API Permissions.
  • La sincronizzazione automatica con le coordinate sullo schermo è disponibile per Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensor e Magnetometer.

API dei sensori generici disponibili

Al momento della stesura di questo articolo, sono disponibili diversi sensori con cui puoi fare esperimenti.

Sensori di movimento:

  • Accelerometer
  • Gyroscope
  • LinearAccelerationSensor
  • AbsoluteOrientationSensor
  • RelativeOrientationSensor
  • GravitySensor

Sensori ambientali:

  • AmbientLightSensor (dietro il flag #enable-generic-sensor-extra-classes in Chromium).
  • Magnetometer (dietro il flag #enable-generic-sensor-extra-classes in Chromium).

Rilevamento delle caratteristiche

Il rilevamento delle funzionalità delle API hardware è complicato, poiché devi rilevare sia se il browser supporta l'interfaccia in questione, sia se il dispositivo è dotato del sensore corrispondente. Verificare se il browser supporta un'interfaccia è semplice. Sostituisci Accelerometer con uno qualsiasi di le altre interfacce indicate 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 anche provare a connetterti al sensore. Questo esempio illustra come procedere.

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, una 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 faccio a utilizzarli?

I sensori sono un'area che potrebbe richiedere una breve introduzione. Se hai familiarità con i sensori, puoi passa direttamente alla sezione pratica di programmazione. In caso contrario, diamo un'occhiata a ciascun sensore supportato.

Accelerometro e sensore di accelerazione lineare

Misurazioni del sensore dell'accelerometro

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 si trova in caduta libera lineare, il totale misurato l'accelerazione è pari a 0 m/s2 mentre, quando un dispositivo è appoggiato orizzontalmente su un tavolo, verso l'alto (asse Z) sarà uguale alla gravità della Terra, ovvero g ≈ +9,8 m/s2 come misura la forza del tavolo che spinge il dispositivo verso l'alto. Se invii il dispositivo a destra, l'accelerazione sull'asse X sarebbe positiva o negativa se il dispositivo viene accelerato da da destra verso sinistra.

Gli accelerometri possono essere utilizzati per, ad esempio, conteggio dei passi, rilevamento dei movimenti o semplice orientamento del dispositivo. Molto spesso, le misurazioni dell'accelerometro vengono combinate con i dati di altre fonti per creano sensori di fusione, come i sensori di orientamento.

La LinearAccelerationSensor misura l'accelerazione applicata al dispositivo che ospita il sensore, escluso il contributo della gravità. Quando un dispositivo è a riposo, ad esempio appoggiato sul tavolo, il sensore misura un'accelerazione di ≈ 0 m/s2 su tre assi.

Sensore di gravità

È già possibile per gli utenti ricavare manualmente letture vicine a quelle di un sensore di gravità esaminando manualmente le letture di Accelerometer e LinearAccelerometer, ma questa operazione può essere complicata e dipendere dall'accuratezza 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ù precisi in base all'hardware dell'utente ed essere più facili da utilizzare termini sull'ergonomia delle API. La GravitySensor restituisce l'effetto di accelerazione lungo gli assi X, Y e Z del dispositivo a causa della gravità.

Giroscopio

Misurazioni del sensore 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 consumatori I dispositivi dispongono di funzionalità meccaniche (MEMS) i giroscopi, ovvero sensori inerziali che misurano la velocità di rotazione in base a forza inerziale di Coriolis. I giroscopi MEMS sono soggetti a derive causate dalla sensibilità gravitazionale del sensore che deforma il sistema meccanico interno del sensore. I giroscopi oscillano a frequenze relativamente alte, ad esempio 10 kHz e quindi potrebbe consumare più energia rispetto ad altri sensori.

Sensori di orientamento

Misurazioni del sensore di orientamento assoluto

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 stazionario.

Tutti i moderni framework JavaScript 3D supportano i quaternioni. e le matrici di rotazione per rappresentare la rotazione; tuttavia, se utilizzi direttamente WebGL, OrientationSensor offre comodamente sia una Proprietà quaternion e un populateMatrix()metodo. Ecco alcuni snippet:

three.js

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

BABYLON

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

WebGL

// 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à virtuale e realtà aumentata.

Per saperne di più sui sensori di movimento, sui casi d'uso avanzati e sui requisiti, consulta il documento spiegativo sui sensori di movimento.

Sincronizzazione con le coordinate dello schermo

Per impostazione predefinita, le letture dei sensori spaziali sono risolte in un sistema di coordinate locale che è associato al dispositivo e non prende l'orientamento dello schermo .

Sistema di coordinate del dispositivo
Sistema di coordinate del dispositivo

Tuttavia, molti casi d'uso, come i giochi o la realtà aumentata e virtuale, richiedono che le letture dei sensori siano risolti in un sistema di coordinate invece vincolato all'orientamento dello schermo.

Sistema di coordinate dello schermo
Sistema di coordinate dello schermo

In precedenza, la rimappatura delle letture del sensore alle coordinate dello schermo doveva essere implementata in JavaScript. Questo approccio non è efficace e aumenta anche in modo significativo la complessità del web il codice dell'applicazione; l'applicazione web deve controllare i cambiamenti nell'orientamento dello schermo ed eseguire le coordinate per le letture dei sensori, cosa che non bisogna fare per gli angoli di Eulero o quaternioni.

L'API Generic Sensor fornisce una soluzione molto più semplice e affidabile. Il sistema di coordinate locale è configurabile per tutti i classi di sensori spaziali definiti: 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 del dispositivo o dello 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 intuitiva! L'interfaccia Sensor ha metodi start() e stop() per controllare lo stato del sensore e diversi gestori eventi per ricevere notifiche sull'attivazione del sensore, sugli errori e sulle letture di nuova disponibilità. Le classi dei sensori in cemento di solito aggiungono i loro attributi di lettura specifici alla base .

Ambiente di sviluppo

Durante lo sviluppo potrai utilizzare i sensori tramite localhost. Se stai sviluppando 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 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 la rotazione, quaternione di un modello 3D. model è un'istanza della classe three.js Object3D che ha una proprietà quaternion. La il seguente snippet di codice telefono di orientamento La demo illustra 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 verrà applicato alla rotazione model 3D all'interno della scena WebGL.

Il sensore aggiorna l'orientamento del modello 3D
Il sensore aggiorna l'orientamento di un modello 3D

Punzonmetro

Il seguente snippet di codice è estratto dalla demo del punchmeter, che mostra come il sensore di accelerazione lineare può essere utilizzato per calcolare la velocità massima di un dispositivo supponendo 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 all'integrale della funzione di accelerazione.

Demo dell&#39;applicazione web per la misurazione della velocità
Misurazione della velocità di perforazione

Debug e override dei sensori con Chrome DevTools

In alcuni casi non è necessario un dispositivo fisico per utilizzare l'API Generic Sensor. Chrome DevTools offre un grande supporto simulazione dell'orientamento del dispositivo.

Chrome DevTools utilizzato per eseguire l&#39;override dei dati di orientamento personalizzato di un telefono virtuale
Simulazione dell'orientamento del dispositivo con Chrome DevTools

Privacy e sicurezza

Le letture dei sensori sono dati sensibili che possono essere soggetti a vari attacchi da parte di 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. Nella Per fare pratica, per usare l'API Generic Sensor dovrai accedere alla tua pagina tramite HTTPS. Durante lo sviluppo puoi farlo tramite http://localhost, ma per la produzione dovrai avere HTTPS sul tuo server. Consulta la raccolta Sicurezza e protezione per le best practice e linee guida.

Integrazione dei criteri relativi alle autorizzazioni

Integrazione dei criteri relativi alle autorizzazioni nella sezione Generica L'API 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 frame secondari della stessa origine, impedendo così agli iframe multiorigine di leggere i dati dei sensori non approvati. Questo comportamento predefinito può essere modificato abilitando o disattivando in modo esplicito il funzionalità controllate dalle norme.

Lo snippet riportato di seguito mostra la concessione dell'accesso ai dati dell'accelerometro a un iframe cross-origin, il che significa che ora è possibile creare oggetti Accelerometer o LinearAccelerationSensor.

<iframe src="https://third-party.com" allow="accelerometer" />

L'invio delle letture del sensore può essere sospeso

Le letture dei sensori sono accessibili solo da una pagina web visibile, ovvero quando l'utente a interagire con quest'ultima. Inoltre, i dati dei sensori non vengono forniti al frame principale se l'utente imposta lo stato attivo su un frame secondario multiorigine. Questo impedisce al frame principale di dedurre l'input dell'utente.

Passaggi successivi

Esiste un insieme di classi di sensori già specificate da implementare nel prossimo futuro, come Ambient Light Sensor o Proximity Sensor; tuttavia, grazie alla grande estendibilità del framework Generic Sensor, possiamo prevedere l'aspetto di altre nuove classi che rappresentano vari tipi di sensori.

Un'altra area 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 implementare nuove funzionalità necessarie per gli sviluppatori.

Puoi dare il tuo contributo.

Le specifiche del sensore hanno raggiunto il livello di maturità Candidato per la raccomandazione, pertanto il feedback degli sviluppatori web e dei browser è molto apprezzato. Permettici sapere quali funzionalità sarebbe fantastico aggiungere o se c'è qualcosa che vorresti modificare nel l'API corrente.

Non esitare a segnalare problemi relativi alle specifiche, nonché bug per l'implementazione di Chrome.

Risorse

Ringraziamenti

Questo articolo è stato esaminato da Joe Medley e Kayce Basques. Immagine hero di Misko tramite Wikimedia Commons.