Sensoren voor het web

Gebruik de Generic Sensor API om toegang te krijgen tot sensoren op het apparaat, zoals versnellingsmeters, gyroscopen en magnetometers.

Tegenwoordig worden sensorgegevens in veel platformspecifieke toepassingen gebruikt om gebruiksscenario's mogelijk te maken, zoals meeslepende gaming, fitnesstracking en augmented of virtual reality. Zou het niet cool zijn om de kloof tussen platformspecifieke en webapplicaties te overbruggen? Voer de Generieke Sensor API in, voor internet!

Wat is de generieke sensor-API?

De Generic Sensor API is een reeks interfaces die sensorapparaten blootstellen aan het webplatform. De API bestaat uit de Sensor en een reeks concrete sensorklassen die daar bovenop zijn gebouwd. Het hebben van een basisinterface vereenvoudigt het implementatie- en specificatieproces voor de concrete sensorklassen. Kijk bijvoorbeeld eens naar de klasse Gyroscope . Het is superklein! De kernfunctionaliteit wordt gespecificeerd door de basisinterface, en Gyroscope breidt deze slechts uit met drie attributen die de hoeksnelheid vertegenwoordigen.

Sommige sensorklassen zijn gekoppeld aan daadwerkelijke hardwaresensoren, zoals bijvoorbeeld de accelerometer- of gyroscoopklassen. Dit worden laagniveausensoren genoemd. Andere sensoren, ook wel fusiesensoren genoemd, voegen gegevens van verschillende sensoren op laag niveau samen om informatie bloot te leggen die een script anders zou moeten berekenen. De AbsoluteOrientation sensor biedt bijvoorbeeld een kant-en-klare vier-bij-vier-rotatiematrix op basis van de gegevens verkregen van de versnellingsmeter, gyroscoop en magnetometer.

Je zou denken dat het webplatform al sensordata levert en daar heb je helemaal gelijk in! DeviceMotion en DeviceOrientation gebeurtenissen maken bijvoorbeeld bewegingssensorgegevens openbaar. Dus waarom hebben we een nieuwe API nodig?

Vergeleken met de bestaande interfaces biedt Generic Sensor API een groot aantal voordelen:

  • Generic Sensor API is een sensorframework dat eenvoudig kan worden uitgebreid met nieuwe sensorklassen en elk van deze klassen behoudt de generieke interface. De clientcode die voor het ene sensortype is geschreven, kan met zeer weinig aanpassingen worden hergebruikt voor een ander sensortype!
  • U kunt de sensor configureren. U kunt bijvoorbeeld de bemonsteringsfrequentie instellen die geschikt is voor uw toepassingsbehoeften.
  • U kunt detecteren of er een sensor beschikbaar is op het platform.
  • Sensormetingen hebben zeer nauwkeurige tijdstempels, waardoor een betere synchronisatie met andere activiteiten in uw toepassing mogelijk is.
  • Sensordatamodellen en coördinatensystemen zijn duidelijk gedefinieerd, waardoor browserleveranciers interoperabele oplossingen kunnen implementeren.
  • De op Generieke Sensoren gebaseerde interfaces zijn niet gebonden aan de DOM (wat betekent dat ze geen navigator of window zijn), en dit opent toekomstige mogelijkheden voor het gebruik van de API binnen servicemedewerkers of voor de implementatie ervan in headless JavaScript-runtimes, zoals ingebedde apparaten.
  • Beveiligings- en privacyaspecten hebben de hoogste prioriteit voor de Generieke Sensor API en bieden een veel betere beveiliging in vergelijking met oudere sensor-API's. Er is integratie met de Permissions API.
  • Automatische synchronisatie met schermcoördinaten is beschikbaar voor Accelerometer , Gyroscope , LinearAccelerationSensor , AbsoluteOrientationSensor , RelativeOrientationSensor en Magnetometer .

Beschikbare generieke sensor-API's

Op het moment van schrijven zijn er verschillende sensoren waarmee je kunt experimenteren.

Bewegingssensoren:

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

Omgevingssensoren:

  • AmbientLightSensor (achter de vlag #enable-generic-sensor-extra-classes in Chromium.)
  • Magnetometer (achter de vlag #enable-generic-sensor-extra-classes in Chromium.)

Functiedetectie

Functiedetectie van hardware-API's is lastig, omdat je zowel moet detecteren of de browser de betreffende interface ondersteunt, als of het apparaat over de bijbehorende sensor beschikt. Controleren of de browser een interface ondersteunt, is eenvoudig. (Vervang Accelerometer door een van de andere hierboven genoemde interfaces.)

if ('Accelerometer' in window) {
  // The `Accelerometer` interface is supported by the browser.
  // Does the device have an accelerometer, though?
}

Voor een daadwerkelijk betekenisvol functiedetectieresultaat moet u ook proberen verbinding te maken met de sensor. Dit voorbeeld illustreert hoe u dat kunt doen.

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

Polyvulling

Voor browsers die de Generic Sensor API niet ondersteunen, is een polyfill beschikbaar. Met de polyfill kunt u alleen de relevante sensorimplementaties laden.

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

Wat zijn al deze sensoren? Hoe kan ik ze gebruiken?

Sensoren is een gebied dat misschien een korte introductie nodig heeft. Als u bekend bent met sensoren, kunt u direct naar het praktische codeergedeelte gaan. Laten we anders elke ondersteunde sensor in detail bekijken.

Accelerometer en lineaire versnellingssensor

Accelerometersensormetingen

De Accelerometer sensor meet de versnelling van een apparaat dat de sensor host op drie assen (X, Y en Z). Deze sensor is een traagheidssensor, wat betekent dat wanneer het apparaat zich in een lineaire vrije val bevindt, de totale gemeten versnelling 0 m/s 2 zou zijn, en wanneer een apparaat plat op een tafel ligt, de versnelling in opwaartse richting (Z-as) zal zijn gelijk zijn aan de zwaartekracht van de aarde, dwz g ≈ +9,8 m/s 2 , aangezien deze de kracht meet van de tafel die het apparaat omhoog duwt. Als u het apparaat naar rechts duwt, is de versnelling op de X-as positief, of negatief als het apparaat van rechts naar links wordt versneld.

Accelerometers kunnen worden gebruikt voor zaken als: stappen tellen, bewegingsdetectie of eenvoudige apparaatoriëntatie. Heel vaak worden metingen van de versnellingsmeter gecombineerd met gegevens uit andere bronnen om fusiesensoren te creëren, zoals oriëntatiesensoren.

De LinearAccelerationSensor meet de versnelling die wordt toegepast op het apparaat dat de sensor host, exclusief de bijdrage van de zwaartekracht. Wanneer een apparaat in rust is, bijvoorbeeld plat op tafel, meet de sensor een versnelling van ≈ 0 m/s 2 op drie assen.

Zwaartekracht sensor

Het is al mogelijk voor gebruikers om handmatig metingen af ​​te leiden die dicht bij die van een zwaartekrachtsensor liggen door handmatig de metingen van Accelerometer en LinearAccelerometer te inspecteren, maar dit kan omslachtig zijn en afhankelijk zijn van de nauwkeurigheid van de waarden die door die sensoren worden geleverd. Platforms zoals Android kunnen zwaartekrachtmetingen leveren als onderdeel van het besturingssysteem, wat goedkoper zou moeten zijn in termen van berekeningen, nauwkeurigere waarden zou moeten opleveren, afhankelijk van de hardware van de gebruiker, en gemakkelijker te gebruiken zou moeten zijn in termen van API-ergonomie. De GravitySensor retourneert het effect van versnelling langs de X-, Y- en Z-as van het apparaat als gevolg van de zwaartekracht.

Gyroscoop

Metingen van gyroscoopsensoren

De Gyroscope meet de hoeksnelheid in radialen per seconde rond de lokale X-, Y- en Z-as van het apparaat. De meeste consumentenapparaten hebben mechanische ( MEMS ) gyroscopen, dit zijn traagheidssensoren die de rotatiesnelheid meten op basis van de traagheid Corioliskracht . MEMS-gyroscopen zijn gevoelig voor drift die wordt veroorzaakt door de zwaartekrachtgevoeligheid van de sensor, waardoor het interne mechanische systeem van de sensor wordt vervormd. Gyroscopen oscilleren op relatief hoge frequenties, bijvoorbeeld 10s kHz, en kunnen daarom meer stroom verbruiken vergeleken met andere sensoren.

Oriëntatie sensoren

Absolute oriëntatiesensormetingen

De AbsoluteOrientationSensor is een fusiesensor die de rotatie van een apparaat meet ten opzichte van het coördinatensysteem van de aarde, terwijl de RelativeOrientationSensor gegevens levert die de rotatie vertegenwoordigen van een apparaat dat bewegingssensoren huisvest in relatie tot een stationair referentiecoördinatensysteem.

Alle moderne 3D JavaScript-frameworks ondersteunen quaternionen en rotatiematrices om rotatie weer te geven; Als u WebGL echter rechtstreeks gebruikt, beschikt de OrientationSensor handig over zowel een quaternion eigenschap als een populateMatrix() -methode . Hier zijn enkele fragmenten:

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

Oriëntatiesensoren maken verschillende gebruiksscenario's mogelijk, zoals meeslepend gamen, augmented en virtual reality.

Voor meer informatie over bewegingssensoren, geavanceerde gebruiksscenario's en vereisten, bekijk het uitlegdocument over bewegingssensoren .

Synchronisatie met schermcoördinaten

Standaard worden de metingen van ruimtelijke sensoren opgelost in een lokaal coördinatensysteem dat aan het apparaat is gebonden en geen rekening houdt met de schermoriëntatie.

Apparaatcoördinatensysteem
Apparaatcoördinatensysteem

Veel gebruiksscenario's, zoals games of augmented en virtual reality, vereisen echter dat sensormetingen worden opgelost in een coördinatensysteem dat in plaats daarvan gebonden is aan de schermoriëntatie.

Schermcoördinatensysteem
Schermcoördinatensysteem

Voorheen moest het opnieuw toewijzen van sensormetingen aan schermcoördinaten in JavaScript worden geïmplementeerd. Deze aanpak is inefficiënt en vergroot ook aanzienlijk de complexiteit van de webapplicatiecode; de webapplicatie moet veranderingen in de schermoriëntatie bekijken en coördinatentransformaties uitvoeren voor sensormetingen, wat niet triviaal is om te doen voor Euler-hoeken of quaternionen.

De Generieke Sensor API biedt een veel eenvoudigere en betrouwbare oplossing! Het lokale coördinatensysteem is configureerbaar voor alle gedefinieerde ruimtelijke sensorklassen: Accelerometer , Gyroscope , LinearAccelerationSensor , AbsoluteOrientationSensor , RelativeOrientationSensor en Magnetometer . Door de optie referenceFrame door te geven aan de sensorobjectconstructor, definieert de gebruiker of de geretourneerde metingen worden omgezet in apparaat- of schermcoördinaten .

// 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' });

Laten we coderen!

De Generieke Sensor API is heel eenvoudig en gemakkelijk te gebruiken! De Sensor-interface heeft start() en stop() methoden om de sensorstatus te controleren en verschillende gebeurtenishandlers voor het ontvangen van meldingen over sensoractivering, fouten en nieuw beschikbare metingen. De betonsensorklassen voegen doorgaans hun specifieke leesattributen toe aan de basisklasse.

Ontwikkelomgeving

Tijdens de ontwikkeling kun je sensoren gebruiken via localhost . Als u voor mobiele apparaten ontwikkelt, stel dan port forwarding in voor uw lokale server en u bent klaar om te rocken!

Wanneer uw code gereed is, implementeert u deze op een server die HTTPS ondersteunt. GitHub-pagina's worden via HTTPS weergegeven, waardoor het een geweldige plek is om uw demo's te delen.

3D-modelrotatie

In dit eenvoudige voorbeeld gebruiken we de gegevens van een absolute oriëntatiesensor om het rotatiequaternion van een 3D-model te wijzigen. Het model is een Object3D klasse-instantie van drie.js met een quaternion eigenschap. Het volgende codefragment uit de demo van de oriëntatietelefoon illustreert hoe de absolute oriëntatiesensor kan worden gebruikt om een ​​3D-model te roteren.

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

De oriëntatie van het apparaat wordt weerspiegeld in de 3D- model binnen de WebGL-scène.

Sensor werkt de oriëntatie van het 3D-model bij
Sensor werkt de oriëntatie van een 3D-model bij

Perforatiemeter

Het volgende codefragment is afkomstig uit de punchmeter-demo en illustreert hoe de lineaire versnellingssensor kan worden gebruikt om de maximale snelheid van een apparaat te berekenen, ervan uitgaande dat het aanvankelijk stilstaat.

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

De huidige snelheid wordt berekend als een benadering van de integraal van de versnellingsfunctie.

Demo webapplicatie voor het meten van de ponssnelheid
Meting van een ponssnelheid

Foutopsporing en sensoroverschrijving met Chrome DevTools

In sommige gevallen heb je geen fysiek apparaat nodig om met de Generieke Sensor API te spelen. Chrome DevTools biedt geweldige ondersteuning voor het simuleren van apparaatoriëntatie .

Chrome DevTools gebruikt om de aangepaste oriëntatiegegevens van een virtuele telefoon te overschrijven
Apparaatoriëntatie simuleren met Chrome DevTools

Privacy en veiligheid

Sensormetingen zijn gevoelige gegevens die kunnen worden blootgesteld aan verschillende aanvallen van kwaadaardige webpagina's. Implementaties van generieke sensor-API's leggen een aantal beperkingen op om de mogelijke beveiligings- en privacyrisico's te beperken. Met deze beperkingen moet rekening worden gehouden door ontwikkelaars die van plan zijn de API te gebruiken, dus laten we ze kort opsommen.

Alleen HTTPS

Omdat Generic Sensor API een krachtige functie is, staat de browser deze alleen toe in beveiligde contexten. In de praktijk betekent dit dat u, om de Generic Sensor API te gebruiken, toegang tot uw pagina moet krijgen via HTTPS. Tijdens de ontwikkeling kunt u dit doen via http://localhost , maar voor productie heeft u HTTPS op uw server nodig. Zie de Veilige collectie voor best practices en richtlijnen.

Machtigingen Beleidsintegratie

De integratie van het machtigingsbeleid in de Generic Sensor API regelt de toegang tot sensorgegevens voor een frame.

Standaard kunnen de Sensor objecten alleen worden gemaakt binnen een hoofdframe of subframes van dezelfde oorsprong, waardoor wordt voorkomen dat cross-origin iframes ongeoorloofd sensorgegevens lezen. Dit standaardgedrag kan worden gewijzigd door de overeenkomstige beleidsgestuurde functies expliciet in of uit te schakelen.

Het onderstaande fragment illustreert het verlenen van toegang tot accelerometergegevens aan een cross-origin iframe, wat betekent dat daar nu Accelerometer of LinearAccelerationSensor -objecten kunnen worden gemaakt.

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

De levering van sensormetingen kan worden opgeschort

Sensormetingen zijn alleen toegankelijk via een zichtbare webpagina, dat wil zeggen wanneer de gebruiker er daadwerkelijk mee communiceert. Bovendien zouden er geen sensorgegevens aan het ouderframe worden geleverd als de gebruikersfocus verandert naar een cross-origin subframe. Dit voorkomt dat het bovenliggende frame gebruikersinvoer afleidt.

Wat is het volgende?

Er is een reeks reeds gespecificeerde sensorklassen die in de nabije toekomst zullen worden geïmplementeerd, zoals de omgevingslichtsensor of de nabijheidssensor ; Dankzij de grote uitbreidbaarheid van het Generic Sensor-framework kunnen we echter anticiperen op de verschijning van nog meer nieuwe klassen die verschillende sensortypen vertegenwoordigen.

Een ander belangrijk gebied voor toekomstig werk is het verbeteren van de Generieke Sensor API zelf; de Generieke Sensor-specificatie is momenteel een Kandidaataanbeveling, wat betekent dat er nog tijd is om verbeteringen aan te brengen en nieuwe functionaliteit te bieden die ontwikkelaars nodig hebben.

Je kan helpen!

De sensorspecificaties bereikten het volwassenheidsniveau van de Candidate Recommendation . Daarom wordt de feedback van web- en browserontwikkelaars zeer op prijs gesteld. Laat ons weten welke functies leuk zouden zijn om toe te voegen of dat u iets wilt wijzigen in de huidige API.

Aarzel niet om specificatieproblemen en bugs voor de Chrome-implementatie door te geven.

Bronnen

Dankbetuigingen

Dit artikel is beoordeeld door Joe Medley en Kayce Basques . Heldenafbeelding door Misko via Wikimedia Commons .