Capteurs pour le Web

Utilisez l'API Generic Sensor pour accéder aux capteurs de l'appareil, tels que les accéléromètres, les gyroscopes et les magnétomètres.

Alex Shalamov
Alex Shalamov
Mikhail Pozdnyakov
Mikhail Pozdnyakov

Aujourd'hui, les données des capteurs sont utilisées dans de nombreuses applications propres à la plate-forme pour permettre des cas d'utilisation : les jeux vidéo immersifs, le suivi des données de remise en forme, et la réalité augmentée ou virtuelle. Ne serait-il pas cool de ponter l'écart entre les applications Web et spécifiques à une plate-forme ? Découvrez l'API Sensor générique pour le Web.

Qu'est-ce que l'API Generic Sensor ?

L'API Generic Sensor est un ensemble d'interfaces qui exposent de capteurs à la plate-forme Web. L'API se compose de l'interface de base Sensor et d'un ensemble de classes de capteurs concrètes construites par-dessus. Une interface de base simplifie le processus d'implémentation et de spécification des classes de capteurs concrètes. Par exemple, examinez Gyroscope. Il est tout petit ! La la fonctionnalité de base est spécifiée par l'interface de base, et Gyroscope l'étend simplement avec trois qui représentent la vitesse angulaire.

Certaines classes de capteurs s'interfacent avec des capteurs matériels réels, tels que les classes d'accéléromètre ou de gyroscope. On les appelle "capteurs de bas niveau". D'autres capteurs, appelés capteurs de fusion, fusionner les données de plusieurs niveaux inférieurs des capteurs pour exposer les informations qu'un script devrait calculer autrement. Par exemple, le capteur AbsoluteOrientation fournit une matrice de rotation quatre x quatre prête à l'emploi basée sur les données obtenues à partir de l'accéléromètre, du gyroscope et du magnétomètre.

Vous pensez peut-être que la plate-forme Web fournit déjà des données de capteurs, et vous avez tout à fait raison. Pour instance, DeviceMotion et DeviceOrientation exposent les données des capteurs de mouvement. Pourquoi avons-nous besoin d'une nouvelle API ?

L'API Generic Sensor offre de nombreux avantages par rapport aux interfaces existantes:

  • L'API Generic Sensor est un framework de capteurs qui peut être facilement étendu avec de nouvelles classes de capteurs, et chacune de ces classes conservera l'interface générique. Le code client écrit pour un type de capteur peut être réutilisé pour un autre avec très peu de modifications !
  • Vous pouvez configurer le capteur. Par exemple, vous pouvez définir la fréquence d'échantillonnage adaptée à vos des besoins de l'application.
  • Vous pouvez détecter si un capteur est disponible sur la plate-forme.
  • Les relevés des capteurs présentent des horodatages très précis, ce qui permet une meilleure synchronisation avec d'autres dans votre application.
  • Les modèles de données des capteurs et les systèmes de coordonnées sont clairement définis, ce qui permet aux fournisseurs pour implémenter des solutions interopérables.
  • Les interfaces basées sur les capteurs génériques ne sont pas liées au DOM (c'est-à-dire qu'elles ne sont ni des objets navigator ni des objets window). Cela ouvre de nouvelles possibilités d'utilisation de l'API dans les workers de service ou de son implémentation dans les environnements d'exécution JavaScript headless, tels que les appareils intégrés.
  • Les aspects sécurité et confidentialité sont la priorité absolue de l'API Generic Sensor et offrent une sécurité bien meilleure que les anciennes API de capteurs. Il existe une intégration avec l'API Permissions.
  • La synchronisation automatique avec les coordonnées de l'écran est disponible pour Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensor et Magnetometer.

API de capteurs génériques disponibles

Au moment de la rédaction de cet article, vous pouvez tester plusieurs capteurs.

Capteurs de mouvement:

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

Capteurs d'ambiance:

  • AmbientLightSensor (derrière l'indicateur #enable-generic-sensor-extra-classes dans Chromium)
  • Magnetometer (derrière l'indicateur #enable-generic-sensor-extra-classes dans Chromium)

Détection de caractéristiques

La détection des fonctionnalités des API matérielles est délicate, car vous devez détecter à la fois si le navigateur est compatible avec l'interface en question et si l'appareil est équipé du capteur correspondant. Vérification en cours la prise en charge ou non d'une interface par le navigateur est simple. (Remplacez Accelerometer par l'une des autres interfaces mentionnées ci-dessus.)

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

Pour obtenir un résultat de détection de caractéristiques réellement pertinent, vous devez également essayer de vous connecter au capteur. Cet exemple montre comment procéder.

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

Pour les navigateurs qui ne sont pas compatibles avec l'API Generic Sensor, un polyfill est disponible. Le polyfill vous permet ne charge que les capteurs mises en œuvre.

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

À quoi correspondent tous ces capteurs ? Comment les utiliser ?

Les capteurs sont un domaine qui nécessite peut-être une brève introduction. Si vous connaissez déjà les capteurs, vous pouvez directement accéder à la section de codage pratique. Sinon, examinons chacun d'entre eux le capteur vidéo.

Accéléromètre et capteur d'accélération linéaire

mesures du capteur d'accéléromètre

Capteur Accelerometer mesure l'accélération d'un appareil hébergeant le capteur sur trois axes (X, Y et Z). Ce capteur est un capteur inertiel, ce qui signifie que lorsque l'appareil est en chute libre linéaire, l'accélération totale mesurée est de 0 m/s2. Lorsqu'un appareil est posé à plat sur une table, l'accélération vers le haut (axe Z) est égale à la gravité terrestre, c'est-à-dire g ≈ +9,8 m/s2, car il mesure la force de la table qui pousse l'appareil vers le haut. Si vous poussez l'appareil vers la droite, l'accélération sur l'axe X est positive, ou négative si l'appareil est accéléré de droite à gauche.

Les accéléromètres peuvent être utilisés pour le comptage des pas, la détection de mouvement ou l'orientation simple de l'appareil, par exemple. Bien souvent, les mesures de l'accéléromètre sont associées à des données provenant d'autres sources pour créer des capteurs de fusion, tels que des capteurs d'orientation.

La LinearAccelerationSensor mesure l'accélération appliquée à l'appareil qui héberge le capteur, à l'exclusion de la contribution de la gravité. Lorsqu'un appareil est au repos, par exemple posé à plat sur la table, le capteur mesure ~ 0 m/s2 d'accélération sur trois axes.

Capteur de gravité

Les utilisateurs peuvent déjà dériver manuellement des mesures proches de celles d'un capteur de gravité en inspectant manuellement les mesures Accelerometer et LinearAccelerometer, mais cela peut être fastidieux et dépendre de la précision des valeurs fournies par ces capteurs. Des plates-formes telles qu'Android peuvent fournir des mesures de gravité dans le cadre du système d'exploitation, ce qui devrait être moins coûteux en termes de calcul, fournir des valeurs plus précises en fonction du matériel de l'utilisateur et être plus facile à utiliser en termes d'ergonomie de l'API. GravitySensor renvoie l'effet de l'accélération le long des axes X, Y et Z de l'appareil en raison de la gravité.

Gyroscope

<ph type="x-smartling-placeholder">
</ph>
Mesures du gyroscope

Le capteur Gyroscope mesure la vitesse angulaire en radians par seconde autour des axes X, Y et Z locaux de l'appareil. La plupart des appareils grand public sont équipés de gyroscopes mécaniques (MEMS), qui sont des capteurs inertiels qui mesurent la vitesse de rotation en fonction de la force Coriolis inertielle. Les gyroscopes MEMS sont sujets à la dérive causée par la sensibilité gravitationnelle du capteur, qui déforme son système mécanique interne. Les gyroscopes oscillent à des fréquences relativement élevées Des dizaines de kHz et peut donc consommer plus d'énergie que d'autres capteurs.

Capteurs d'orientation

<ph type="x-smartling-placeholder">
</ph>
Mesures du capteur d'orientation absolue

La AbsoluteOrientationSensor est un capteur de fusion qui mesure la rotation d'un appareil par rapport au système de coordonnées terrestre, tandis que RelativeOrientationSensor fournit des données représentant la rotation d'un appareil hébergeant des capteurs de mouvement par rapport à un appareil fixe de coordonnées de référence.

Tous les frameworks JavaScript 3D modernes acceptent les quaternions et les matrices de rotation pour représenter la rotation. Toutefois, si vous utilisez directement WebGL, OrientationSensor dispose à la fois d'une propriété quaternion et d'une méthode populateMatrix(). Voici quelques extraits :

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

Les capteurs d'orientation permettent différents cas d'utilisation, comme les jeux immersifs, les expériences la réalité.

Pour en savoir plus sur les capteurs de mouvement, les cas d'utilisation avancés et les conditions requises, consultez le présentation des capteurs de mouvement.

Synchronisation avec les coordonnées de l'écran

Par défaut, les mesures des capteurs spatiaux sont résolues dans un système de coordonnées local lié à l'appareil et qui ne tient pas compte de l'orientation de l'écran.

<ph type="x-smartling-placeholder">
</ph> Système de coordonnées de l&#39;appareil
Système de coordonnées de l'appareil

Toutefois, de nombreux cas d'utilisation, comme les jeux ou la réalité augmentée et virtuelle, nécessitent que les lectures des capteurs soient résolues dans un système de coordonnées lié à l'orientation de l'écran.

Système de coordonnées de l&#39;écran
Système de coordonnées de l'écran

Auparavant, le remappage des lectures des capteurs aux coordonnées de l'écran devait être implémenté en JavaScript. Cette approche est inefficace et augmente également de manière assez importante la complexité du code de l'application Web. L'application Web doit surveiller les changements d'orientation de l'écran et effectuer des transformations de coordonnées pour les lectures des capteurs, ce qui n'est pas une tâche simple pour les angles d'Euler ou les quaternions.

L'API Generic Sensor fournit une solution beaucoup plus simple et fiable. Le système de coordonnées local est configurable pour toutes les classes de capteurs spatiaux définies : Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensor et Magnetometer. En transmettant l'option referenceFrame au constructeur de l'objet capteur, l'utilisateur détermine si les lectures renvoyées seront résolues dans device ou coordonnées de l'écran.

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

Commençons à coder !

L'API Generic Sensor est très simple à utiliser. L'interface Sensor dispose des méthodes start() et stop() pour contrôler l'état du capteur et plusieurs gestionnaires d'événements pour recevoir des notifications sur l'activation du capteur, les erreurs et les nouvelles lectures disponibles. Les classes de capteurs concrètes ajoutent généralement leurs attributs de lecture spécifiques à la classe de base.

Environnement de développement

Pendant le développement, vous pourrez utiliser les capteurs via localhost. Si vous développez pour appareils mobiles, configurer Transfert de port pour votre serveur local. Tout est prêt !

Lorsque votre code est prêt, déployez-le sur un serveur compatible avec HTTPS. Les pages GitHub sont diffusées via HTTPS, ce qui en fait un lieu idéal pour partager vos démonstrations.

Rotation du modèle 3D

Dans cet exemple simple, nous utilisons les données d'un capteur d'orientation absolue pour modifier le quaternion de rotation d'un modèle 3D. model est une instance de classe three.js Object3D qui possède une propriété quaternion. La l'extrait de code suivant de téléphone d'orientation qui illustre comment utiliser le capteur d'orientation absolue pour faire pivoter un modèle 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'orientation de l'appareil sera reflétée par la rotation model 3D dans la scène WebGL.

Mise à jour de l&#39;orientation du modèle 3D par le capteur
Le capteur met à jour l'orientation d'un modèle 3D

Punchmeter

L'extrait de code suivant est extrait de la démonstration du punchmètre. Il montre comment le capteur d'accélération linéaire peut être utilisé pour calculer la vitesse maximale d'un appareil en supposant qu'il est initialement immobile.

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 vitesse actuelle est calculée sous la forme d'une approximation de l'intégrale de la fonction d'accélération.

Application Web de démonstration pour la mesure de la vitesse de frappe
Mesure de la vitesse d'un coup de poing

Débogage et remplacement des capteurs avec les outils pour les développeurs Chrome

Dans certains cas, vous n'avez pas besoin d'un appareil physique pour jouer avec l'API Generic Sensor. Outils pour les développeurs Chrome est parfaitement compatible avec simuler l'orientation de l'appareil.

Utiliser les outils pour les développeurs Chrome pour remplacer les données d&#39;orientation personnalisées d&#39;un téléphone virtuel
Simuler l'orientation de l'appareil avec les outils pour les développeurs Chrome

Confidentialité et sécurité

Les relevés de capteurs sont des données sensibles qui peuvent faire l'objet de diverses attaques provenant de pages Web malveillantes. Les implémentations des API de capteur génériques appliquent quelques restrictions pour atténuer les risques de sécurité et de confidentialité potentiels. Ces limites doivent être prises en compte par les développeurs qui souhaitent utiliser l'API. Voyons-les brièvement.

HTTPS uniquement

L'API Generic Sensor étant une fonctionnalité puissante, le navigateur ne l'autorise que dans des contextes sécurisés. En pratique, cela signifie que pour utiliser l'API Generic Sensor, vous devez accéder à votre page via HTTPS. Lors du développement, vous pouvez le faire via http://localhost, mais pour la production, vous devez disposer de HTTPS sur votre serveur. Consultez la collection Sécurité pour connaître les bonnes pratiques et les consignes.

Intégration des règles sur les autorisations

L'intégration de la stratégie d'autorisations dans l'API Generic Sensor contrôle l'accès aux données des capteurs pour un frame.

Par défaut, les objets Sensor ne peuvent être créés que dans un frame principal ou des sous-frames de même origine. ce qui empêche les iFrames multi-origines de lire les données de capteurs non autorisées. Ce comportement par défaut peut être modifié en activant ou en désactivant explicitement fonctionnalités contrôlées par des règles.

L'extrait de code ci-dessous montre comment accorder un accès aux données de l'accéléromètre à un iFrame multi-origine, ce qui signifie que des objets Accelerometer ou LinearAccelerationSensor peuvent désormais y être créés.

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

La transmission des relevés des capteurs peut être suspendue

Les relevés des capteurs ne sont accessibles que depuis une page Web visible, c'est-à-dire lorsque l'utilisateur interagir avec elle. De plus, les données des capteurs ne seraient pas fournies au frame parent si le focus de l'utilisateur change pour un sous-frame inter-origine. Cela empêche le frame parent d'inférer l'entrée utilisateur.

Étape suivante

Un ensemble de classes de capteurs déjà spécifiées doit être implémenté dans un avenir proche, comme le capteur de luminosité ambiante ou le capteur de proximité. Toutefois, grâce à la grande extensibilité du framework de capteurs génériques, nous pouvons anticiper l'apparition de nouvelles classes représentant différents types de capteurs.

Un autre domaine important pour les futurs travaux est l'amélioration de l'API Generic Sensor elle-même, la fonction Generic Sensor, La spécification des capteurs est actuellement une recommandation candidate, ce qui signifie qu'il reste du temps pour apporter des corrections et apporter de nouvelles fonctionnalités dont les développeurs ont besoin.

Tu peux m'aider !

Caractéristiques du capteur atteintes Recommandation de candidat niveau de maturité. Par conséquent, les commentaires des développeurs de sites Web et de navigateurs sont très appréciés. Indiquez-nous les fonctionnalités que vous aimeriez ajouter ou les modifications que vous souhaitez apporter à l'API actuelle.

N'hésitez pas à signaler des problèmes de spécification ainsi que des bugs pour l'implémentation de Chrome.

Ressources

Remerciements

Cet article a été relu par Joe Medley et Kayce Basques. Image héros de Misko via Wikimedia Commons.