Sensor untuk web

Gunakan Generic Sensor API untuk mendapatkan akses ke sensor di perangkat seperti akselerometer, giroskop, dan magnetometer.

Alex Shalamov
Alex Shalamov
Mikhail Pozdnyakov
Mikhail Pozdnyakov

Saat ini, data sensor digunakan di banyak aplikasi khusus platform untuk memungkinkan kasus penggunaan seperti game imersif, pelacakan kebugaran, dan augmented reality atau virtual reality. Bukankah keren untuk menjembatani kesenjangan antara yang spesifik untuk platform dan aplikasi web? Masukkan Generic Sensor API, untuk web.

Apa itu Generic Sensor API?

Generic Sensor API adalah sekumpulan antarmuka yang mengekspos perangkat sensor ke platform web. API ini terdiri dari antarmuka Sensor dasar dan sekumpulan class sensor konkret yang dibuat di atasnya. Memiliki antarmuka dasar dapat menyederhanakan proses implementasi dan spesifikasi untuk class sensor konkret. Misalnya, lihat class Gyroscope. Ukurannya sangat kecil! Fungsi inti ditentukan oleh antarmuka dasar, dan Gyroscope hanya memperluasnya dengan tiga atribut yang mewakili kecepatan sudut.

Beberapa class sensor berinteraksi dengan sensor hardware sebenarnya, seperti class akselerometer atau giroskop. Ini disebut sebagai sensor tingkat rendah. Sensor lain, disebut sebagai sensor fusi, menggabungkan data dari beberapa sensor tingkat rendah untuk mengekspos informasi yang perlu dihitung oleh skrip. Misalnya, sensor AbsoluteOrientation menyediakan matriks rotasi empat kali empat yang siap digunakan berdasarkan data yang diperoleh dari akselerometer, giroskop, dan magnetometer.

Anda mungkin berpikir bahwa platform web sudah menyediakan data sensor dan Anda benar sekali! Misalnya, peristiwa DeviceMotion dan DeviceOrientation mengekspos data sensor gerakan. Jadi, mengapa kita memerlukan API baru?

Dibandingkan dengan antarmuka yang ada, Generic Sensor API memberikan banyak keuntungan:

  • Generic Sensor API adalah framework sensor yang dapat dengan mudah diperluas dengan class sensor baru dan setiap class ini akan mempertahankan antarmuka generik. Kode klien yang ditulis untuk satu jenis sensor dapat digunakan kembali untuk jenis sensor lainnya dengan sangat sedikit modifikasi.
  • Anda dapat mengonfigurasi sensor. Misalnya, Anda dapat menetapkan frekuensi pengambilan sampel yang sesuai dengan kebutuhan aplikasi Anda.
  • Anda dapat mendeteksi apakah sensor tersedia di platform.
  • Pembacaan sensor memiliki stempel waktu presisi tinggi, sehingga memungkinkan sinkronisasi yang lebih baik dengan aktivitas lain dalam aplikasi Anda.
  • Model data sensor dan sistem koordinat didefinisikan dengan jelas, sehingga memungkinkan vendor browser untuk menerapkan solusi yang memiliki interoperabilitas.
  • Antarmuka berbasis Sensor Generik tidak terikat pada DOM (artinya bukan objek navigator atau window), dan ini membuka peluang di masa mendatang untuk menggunakan API dalam pekerja layanan atau menerapkannya dalam runtime JavaScript headless, seperti perangkat yang disematkan.
  • Aspek Keamanan dan privasi adalah prioritas utama untuk Generic Sensor API dan memberikan keamanan yang jauh lebih baik dibandingkan dengan API sensor lama. Ada integrasi dengan Permissions API.
  • Sinkronisasi otomatis dengan koordinat layar tersedia untuk Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensor, dan Magnetometer.

API sensor generik yang tersedia

Pada saat penulisan ini, ada beberapa sensor yang dapat Anda coba.

Sensor gerakan:

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

Sensor lingkungan:

  • AmbientLightSensor (Di belakang tanda #enable-generic-sensor-extra-classes di Chromium.)
  • Magnetometer (Di belakang tanda #enable-generic-sensor-extra-classes di Chromium.)

Deteksi fitur

Deteksi fitur API hardware cukup rumit, karena Anda harus mendeteksi apakah browser mendukung antarmuka yang dimaksud, dan apakah perangkat memiliki sensor yang sesuai. Cukup mudah untuk memeriksa apakah browser mendukung antarmuka. (Ganti Accelerometer dengan salah satu antarmuka lain yang disebutkan di atas.)

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

Untuk hasil deteksi fitur yang benar-benar bermakna, Anda juga harus mencoba menghubungkannya ke sensor. Contoh ini menggambarkan cara melakukannya.

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

Isi Ulang

Untuk browser yang tidak mendukung Generic Sensor API, tersedia polyfill. Polyfill memungkinkan Anda memuat implementasi sensor yang relevan saja.

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

Apa saja sensor-sensor ini? Bagaimana cara menggunakannya?

Sensor adalah area yang mungkin memerlukan pengenalan singkat. Jika terbiasa dengan sensor, Anda dapat langsung membuka bagian coding langsung. Jika tidak, mari lihat setiap sensor yang didukung secara mendetail.

Akselerometer dan sensor akselerasi linear

Pengukuran sensor akselerometer

Sensor Accelerometer mengukur akselerasi perangkat yang menghosting sensor pada tiga sumbu (X, Y, dan Z). Sensor ini adalah sensor inersia, yang berarti bahwa saat perangkat berada dalam posisi jatuh bebas linear, total percepatan yang diukur adalah 0 m/s2, dan jika perangkat mendatar di atas meja, akselerasi dalam arah ke atas (sumbu Z) akan sama dengan gravitasi Bumi, yaitu g ≈ +9,8 m/s sebagai gaya mendorong meja. Jika Anda mendorong perangkat ke kanan, akselerasi pada sumbu X akan positif, atau negatif jika perangkat diakselerasi dari kanan ke kiri.

Akselerometer dapat digunakan untuk hal-hal seperti: menghitung langkah, deteksi gerakan, atau orientasi perangkat sederhana. Cukup sering, pengukuran akselerometer digabungkan dengan data dari sumber lain untuk membuat sensor fusi, seperti sensor orientasi.

LinearAccelerationSensor mengukur akselerasi yang diterapkan ke perangkat yang menghosting sensor, tidak termasuk kontribusi gravitasi. Saat perangkat dalam keadaan istirahat, misalnya berbaring di atas meja, sensor akan mengukur akselerasi ≈ 0 m/s2 pada tiga sumbu.

Sensor gravitasi

Pengguna sudah dapat memperoleh pembacaan yang mendekati sensor gravitasi secara manual dengan memeriksa pembacaan Accelerometer dan LinearAccelerometer secara manual, tetapi hal ini dapat merepotkan dan bergantung pada akurasi nilai yang diberikan oleh sensor tersebut. Platform seperti Android dapat menyediakan pembacaan gravitasi sebagai bagian dari sistem operasi, yang seharusnya lebih murah dalam hal komputasi, memberikan nilai yang lebih akurat bergantung pada hardware pengguna, dan lebih mudah digunakan dalam hal ergonomi API. GravitySensor menampilkan efek percepatan di sepanjang sumbu X, Y, dan Z perangkat karena gravitasi.

Giroskop

Pengukuran sensor giroskop

Sensor Gyroscope mengukur kecepatan sudut dalam radian per detik di sekitar sumbu X, Y, dan Z lokal perangkat. Sebagian besar perangkat konsumen memiliki giroskop mekanis (MEMS), yang merupakan sensor inersia yang mengukur laju rotasi berdasarkan gaya Coriolis inersia. Giroskop MEMS rentan penyimpangan yang disebabkan oleh sensitivitas gravitasi sensor yang mengubah bentuk sistem mekanis internal sensor. Giroskop berosilasi pada frekuensi relatif tinggi, misalnya, Puluhan kHz, dan oleh karena itu, mungkin mengonsumsi lebih banyak daya dibandingkan sensor lain.

Sensor orientasi

Pengukuran sensor orientasi absolut

AbsoluteOrientationSensor adalah sensor fusi yang mengukur rotasi perangkat dalam kaitannya dengan sistem koordinat Bumi, sedangkan RelativeOrientationSensor menyediakan data yang mewakili rotasi perangkat yang menghosting sensor gerakan sehubungan dengan sistem koordinat referensi stasioner.

Semua framework JavaScript 3D modern mendukung kuaternion dan matriks rotasi untuk merepresentasikan rotasi. Namun, jika Anda menggunakan WebGL secara langsung, OrientationSensor dengan mudah memiliki properti quaternion dan metode populateMatrix(). Berikut beberapa cuplikannya:

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

Sensor orientasi memungkinkan berbagai kasus penggunaan, seperti game imersif, augmented reality, dan virtual.

Untuk mengetahui informasi selengkapnya tentang sensor gerakan, kasus penggunaan lanjutan, dan persyaratan, lihat dokumen penjelasan sensor gerakan.

Sinkronisasi dengan koordinat layar

Secara default, pembacaan sensor spasial diselesaikan dalam sistem koordinat lokal yang terikat dengan perangkat dan tidak mempertimbangkan orientasi layar.

Sistem koordinat perangkat
Sistem koordinat perangkat

Namun, banyak kasus penggunaan seperti game atau augmented reality dan virtual reality memerlukan pembacaan sensor untuk diselesaikan dalam sistem koordinat yang terikat dengan orientasi layar.

Sistem koordinat layar
Sistem koordinat layar

Sebelumnya, pemetaan ulang pembacaan sensor ke koordinat layar harus diterapkan dalam JavaScript. Pendekatan ini tidak efisien dan juga secara signifikan meningkatkan kompleksitas kode aplikasi web; aplikasi web harus mengamati perubahan orientasi layar dan melakukan transformasi koordinat untuk pembacaan sensor, yang bukan hal mudah yang harus dilakukan untuk sudut Euler atau kuarternion.

Generic Sensor API menyediakan solusi yang jauh lebih sederhana dan andal! Sistem koordinat lokal dapat dikonfigurasi untuk semua class sensor spasial yang ditentukan: Accelerometer, Gyroscope, LinearAccelerationSensor, AbsoluteOrientationSensor, RelativeOrientationSensor, dan Magnetometer. Dengan meneruskan opsi referenceFrame ke konstruktor objek sensor, pengguna menentukan apakah pembacaan yang ditampilkan akan diselesaikan dalam koordinat perangkat atau layar.

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

Ayo membuat kode!

Generic Sensor API sangat sederhana dan mudah digunakan. Antarmuka Sensor memiliki metode start() dan stop() untuk mengontrol status sensor dan beberapa pengendali peristiwa untuk menerima notifikasi tentang aktivasi sensor, error, dan pembacaan yang baru tersedia. Class sensor konkret biasanya menambahkan atribut pembacaan spesifiknya ke class dasar.

Lingkungan pengembangan

Selama pengembangan, Anda akan dapat menggunakan sensor melalui localhost. Jika Anda mengembangkan aplikasi untuk perangkat seluler, siapkan penerusan port untuk server lokal, dan Anda siap menggunakannya.

Jika kode Anda sudah siap, deploy kode di server yang mendukung HTTPS. Halaman GitHub ditayangkan melalui HTTPS, menjadikannya tempat yang tepat untuk membagikan demo Anda.

Rotasi model 3D

Dalam contoh sederhana ini, kita menggunakan data dari sensor orientasi absolut untuk mengubah kuaternion rotasi model 3D. model adalah instance class Object3D tiga.js yang memiliki properti quaternion. Cuplikan kode berikut dari demo ponsel orientasi berikut, mengilustrasikan bagaimana sensor orientasi absolut dapat digunakan untuk memutar model 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();
}

Orientasi perangkat akan tercermin dalam rotasi model 3D dalam scene WebGL.

Sensor memperbarui orientasi model 3D
Sensor memperbarui orientasi model 3D

Pengukur Tinta

Cuplikan kode berikut diekstrak dari demo punchmeter, yang menggambarkan cara sensor akselerasi linear dapat digunakan untuk menghitung kecepatan maksimum perangkat dengan asumsi bahwa sensor tersebut awalnya tidak bergerak.

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

Kecepatan saat ini dihitung sebagai perkiraan dengan integral fungsi percepatan.

Aplikasi web demo untuk pengukuran kecepatan punch
Pengukuran kecepatan pukulan

Proses debug dan penggantian sensor dengan Chrome DevTools

Dalam beberapa kasus, Anda tidak memerlukan perangkat fisik untuk bermain dengan Generic Sensor API. Chrome DevTools memiliki dukungan yang bagus untuk menyimulasikan orientasi perangkat.

Chrome DevTools digunakan untuk mengganti data orientasi kustom ponsel virtual
Menyimulasikan orientasi perangkat dengan Chrome DevTools

Privasi dan keamanan

Pembacaan sensor adalah data sensitif yang dapat menjadi sasaran berbagai serangan dari halaman web berbahaya. Implementasi Generic Sensor API menerapkan beberapa batasan untuk mengurangi kemungkinan risiko keamanan dan privasi. Batasan ini harus dipertimbangkan oleh developer yang ingin menggunakan API, jadi mari kita cantumkan secara singkat.

Hanya HTTPS

Karena Generic Sensor API adalah fitur yang canggih, browser hanya mengizinkannya pada konteks yang aman. Pada praktiknya, untuk menggunakan Generic Sensor API, Anda harus mengakses halaman melalui HTTPS. Selama pengembangan, Anda dapat melakukannya melalui http://localhost, tetapi untuk produksi, Anda harus memiliki HTTPS di server. Lihat koleksi Aman dan terlindungi untuk praktik terbaik dan panduan.

Integrasi Kebijakan Izin

Integrasi Kebijakan Izin dalam Generic Sensor API mengontrol akses ke data sensor untuk frame.

Secara default, objek Sensor hanya dapat dibuat dalam frame utama atau subframe origin yang sama, sehingga mencegah iframe lintas origin membaca data sensor tanpa izin. Perilaku default ini dapat diubah dengan mengaktifkan atau menonaktifkan fitur yang dikontrol kebijakan secara eksplisit.

Cuplikan di bawah mengilustrasikan pemberian akses data akselerometer ke iframe lintas origin, yang berarti kini objek Accelerometer atau LinearAccelerationSensor dapat dibuat di sana.

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

Pengiriman pembacaan sensor dapat ditangguhkan

Pembacaan sensor hanya dapat diakses oleh halaman web yang terlihat, yaitu saat pengguna benar-benar berinteraksi dengannya. Selain itu, data sensor tidak akan diberikan ke frame induk jika fokus pengguna berubah menjadi subframe lintas asal. Ini mencegah frame induk untuk menyimpulkan input pengguna.

Apa langkah selanjutnya?

Ada serangkaian class sensor yang telah ditentukan untuk diterapkan dalam waktu dekat seperti Sensor Cahaya Sekitar atau Sensor Kedekatan; namun, berkat ekstensibilitas framework Sensor Generik yang luar biasa, kami dapat mengantisipasi munculnya lebih banyak class baru yang merepresentasikan berbagai jenis sensor.

Area penting lainnya untuk upaya mendatang adalah meningkatkan Generic Sensor API itu sendiri, spesifikasi Sensor Generik saat ini merupakan Rekomendasi Kandidat, yang berarti masih ada waktu untuk melakukan perbaikan dan menghadirkan fungsi baru yang dibutuhkan developer.

Anda dapat membantu.

Spesifikasi sensor mencapai tingkat kematangan Rekomendasi Kandidat, sehingga, masukan dari developer web dan browser sangat dihargai. Beri tahu kami fitur apa saja yang sebaiknya ditambahkan atau jika ada sesuatu yang ingin Anda ubah di API saat ini.

Jangan ragu untuk melaporkan masalah spesifikasi serta bugs untuk implementasi Chrome.

Referensi

Ucapan terima kasih

Artikel ini ditinjau oleh Joe Medley dan Kayce Basques. Banner besar oleh Misko melalui Wikimedia Commons.