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 ? Saisissez le API Generic Sensor, 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 des éléments de base l'interface Sensor et un ensemble d'éléments des classes de capteurs intégrées. Une interface de base simplifie l'implémentation et la spécification pour les classes de capteurs concrètes. Par exemple, examinez Gyroscope. Il est très 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 sont connectées à des capteurs matériels réels, tels que l'accéléromètre ou du 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, Capteur AbsoluteOrientation fournit une matrice de rotation quatre par quatre prête à l'emploi basée sur les données obtenues à partir du un accéléromètre, un gyroscope et un magnétomètre.

Vous pensez peut-être que la plate-forme Web fournit déjà des données de capteurs et que 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 pouvant être facilement étendu à 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 à votre 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 un capteur générique ne sont pas liées au DOM (ce qui signifie qu'elles ne sont pas des navigator). ni window), ce qui ouvre de futures opportunités d'utilisation de l'API dans le service ou leur mise en œuvre dans des environnements d'exécution JavaScript headless, tels que appareils.
  • La sécurité et la confidentialité sont la priorité absolue du capteur générique et offrent une bien meilleure sécurité que les anciennes API de capteurs. L'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 ce document, 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 valeurs suivantes : 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 significatif pour la détection de caractéristiques, 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 prennent pas en charge 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 peut nécessiter une brève présentation. Si vous connaissez les capteurs, passez directement à la section pratique sur le codage. Sinon, examinons chacun d'entre eux le capteur vidéo.

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

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Mesures du capteur de l'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 inertial, ce qui signifie que lorsque l'appareil est en chute libre linéaire, la longueur totale mesurée l'accélération est de 0 m/s2, et lorsqu'un appareil est posé à plat sur une table, l'accélération vers le haut (axe Z) sera égal à la gravité terrestre, c'est-à-dire g ~ +9,8 m/s2, il mesure la force de la table qui pousse l'appareil vers le haut. Si vous poussez l'appareil l'accélération sur l'axe X est positive ou négative si l'appareil est accéléré la droite vers la gauche.

Les accéléromètres peuvent être utilisés pour comptabiliser les pas, détecter les mouvements ou utiliser un simple appareil, par exemple. l'orientation. Bien souvent, les mesures de l'accéléromètre sont combiné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 ont déjà la possibilité d'obtenir manuellement des mesures proches de celles d'un capteur de gravité en inspecter manuellement les relevés Accelerometer et LinearAccelerometer, mais cela peut être fastidieux et dépendent de la justesse des valeurs fournies par ces capteurs. Les plates-formes comme Android peuvent fournissent des relevés de gravité dans le cadre du système d'exploitation, ce qui devrait être moins cher le calcul, fournir des valeurs plus précises en fonction du matériel de l'utilisateur et être plus faciles à utiliser dans en termes d'ergonomie des API. La GravitySensor renvoie l'effet d'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> <ph type="x-smartling-placeholder">
</ph> Mesures du gyroscope

Le capteur Gyroscope mesure vitesse angulaire en radians par seconde autour des axes X, Y et Z locaux de l'appareil. La plupart des consommateurs les appareils disposent d'un mécanisme mécanique (MEMS) les gyroscopes, des capteurs inertiaux qui mesurent la vitesse de rotation en fonction force d'inertie de Coriolis. Les gyroscopes MEMS sont sujets à problèmes à la dérive causée par la sensibilité gravitationnelle du capteur, qui déforme 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> <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 sont compatibles avec les quaternions et des matrices de rotation pour représenter la rotation. Toutefois, si vous utilisez WebGL directement, OrientationSensor dispose à la fois d'un Propriété quaternion et un 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 qui est lié à l'appareil et qui ne prend pas en compte l'orientation de l'écran Google Cloud.

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

Toutefois, dans de nombreux cas d'utilisation, comme les jeux ou la réalité virtuelle ou augmentée, les mesures des capteurs doivent être résolu dans un système de coordonnées qui est plutôt lié à l'orientation de l'écran.

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

Auparavant, le remappage des relevés de capteurs avec les coordonnées de l'écran devait être implémenté en JavaScript. Cette approche est inefficace et augmente considérablement la complexité du Web code d'application ; l'application Web doit surveiller les changements d'orientation de l'écran et effectuer les coordonnées pour les relevés de capteurs, ce qui n'est pas chose aisée pour les angles d'Euler ou quaternions.

L'API Generic Sensor offre 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' });

C'est parti !

L'API Generic Sensor est très simple d'utilisation. L'interface du capteur start() et stop() pour contrôler l'état des capteurs et plusieurs des gestionnaires d'événements pour recevoir des notifications sur l'activation des capteurs, les erreurs et les nouvelles les relevés de température. En général, les classes de capteurs concrètes ajoutent leurs attributs de lecture spécifiques à la 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 la rotation quaternion d'un modèle 3D. model est une balise 3.js. Instance de classe Object3D ayant un 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 une rotation model 3D dans la scène WebGL.

<ph type="x-smartling-placeholder">
</ph> Le capteur met à jour l&#39;orientation du modèle 3D
Le capteur met à jour l'orientation d'un modèle 3D.
.

Ponctomètre

L'extrait de code suivant est extrait du démonstration de l'outil Punchmeter, illustrant comment le capteur d'accélération linéaire peut être utilisé pour calculer la vitesse maximale d'une appareil en partant du principe 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.

<ph type="x-smartling-placeholder">
</ph> Application Web de démonstration pour la mesure de la vitesse de poinçon
Mesure de la vitesse de perforation
.

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.

<ph type="x-smartling-placeholder">
</ph> 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 d'API Generic Sensor imposent quelques limites pour réduire les risques de sécurité et les risques liés à la confidentialité. Ces limites doivent être prises en compte par les développeurs qui ont l'intention d'utiliser d'API. Récapitulons-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. Dans cela signifie que pour utiliser l'API Generic Sensor, vous devez accéder à votre page via HTTPS. Pendant le développement, vous pouvez le faire via http://localhost, mais pour la production, n'ont pas besoin d'accéder au protocole HTTPS sur votre serveur. Consultez la section Sécurité et protection pour connaître les bonnes pratiques. et consignes.

Intégration des règles d'autorisation

L'intégration des règles d'autorisation dans la documentation L'API Sensor contrôle l'accès aux données des capteurs pour une image.

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 des objets Accelerometer ou LinearAccelerationSensor peuvent désormais y être créés.

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

L'envoi des relevés des capteurs peut être suspendu

Les relevés des capteurs ne sont accessibles que par une page Web visible, c'est-à-dire lorsque l'utilisateur interagir avec elle. De plus, les données des capteurs ne sont pas transmises à l'image parente si l'utilisateur les changements de focus sur un sous-frame d'origines multiples. Cela empêche le frame parent de déduire l'entrée utilisateur.

Étape suivante

Un ensemble de classes de capteurs déjà spécifiées sera bientôt implémenté, par exemple Capteur de luminosité ambiante ou Proximity Sensor (Capteur de proximité) Cependant, grâce à la grande extensibilité Generic Sensor Framework, nous pouvons anticiper l'apparition d'encore plus de nouvelles classes représentant différentes 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 bibliothèque 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. Laissez-nous quelles fonctionnalités ajouteriez-vous ou s'il y a quelque chose que vous aimeriez modifier dans le l'API actuelle.

N'hésitez pas à nous signaler d'autres problèmes liés aux spécifications. comme des bugs pour l'implémentation de Chrome.

Ressources

Remerciements

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