1. 導入
電話などの現代的なハードウェアでは、いくつかの異なるモーションセンサーを利用できる。
モーションセンサーは Generic Sensor API [GENERIC-SENSOR] を拡張し、 低レベルセンサーおよびフュージョンセンサーのクラスを公開する。この文書は、 これらのセンサー間の関係を説明する。
低レベルセンサーには次が含まれる:
上記のセンサーからのデータを異なる方法で使用することで、複数の新しいセンサーを作成できる。 これらは一般にフュージョンセンサーとして知られる。
2. セキュリティとプライバシーに関する考慮事項
Generic Sensor API [GENERIC-SENSOR] で説明されているものを超える、 特定のセキュリティおよびプライバシーに関する考慮事項はない。
3. 低レベルセンサー
3.1. 加速度計
生の 加速度計 センサーは、3 つの異なる方向における加速度の変化を測定するが、重力の影響を受ける。Accelerometer インターフェイスは、[ACCELEROMETER] 仕様で定義される。
加速度計センサーは 慣性フレーム センサーである。これは、デバイスが自由落下している場合、落下方向の加速度は 0 m/s2 であり、 デバイスがテーブル上に平らに置かれている場合、上向き方向の加速度は地球の 重力、すなわち g ≡ 9.8 m/s2 に等しくなることを意味する。 テーブルがデバイスを上向きに押す力を測定しているためである。
加速度計はそれ単体ではあまり有用ではなく、しばしば他のフュージョンセンサーの一部となるが、 揺れ、歩数などの登録といった用途もある。
このようなユースケースでは、開発者は多くの場合、 線形 加速度、すなわち 重力を除いた加速度に関心がある。これは 重力補償と呼ばれる (Linear Acceleration Sensor を参照)。または、開発者は 孤立させた 重力に関心があり、 重力ベクトルを知るために使用する(Gravity Sensor を参照)。これは、磁気コンパスの作成など、 一部の種類のセンサーフュージョンに有用である。
加速度については、通常は大きな変化に関心があり、重力のようなノイズを避けたい。そのため、ハイパスフィルターは 線形 加速度を分離するのに役立ち、ローパス フィルターは 重力を分離するのに役立つ。したがって、ローパスフィルターは 傾きを測定するために有用であり得る。残念ながら、どのような ハイパスフィルターまたは ローパスフィルターも遅延を導入し、それが許容できる場合もあれば そうでない場合もある。
加速度計は加速度を報告するため、速度を得るには積分する必要があることに注意:
v = ∫a×∂t
そして、位置を得るにはもう一度積分する:
x = ∫v×∂t
積分はドリフトを生み、二重積分はそれを増幅する:
a = g×sin(θ), x = ½×at2
したがって、加速度計から得られる位置は非常に不正確で、あまり有用ではない。
3.2. ジャイロスコープ
ジャイロスコープは、 自身に対する相対的な 角速度を検知し、したがって自身の回転を測定する。 これはコリオリ効果と呼ばれる慣性力を用いる。ジャイロスコープはこれを測定するために比較的高い周波数で振動するため、 最も電力を消費するモーションセンサーの 1 つである。これはまた、 同じデバイス上の振動(ランブル)モーターやスピーカーのような他の振動に容易に影響され得ることも意味する。 Gyroscope インターフェイスは、[GYROSCOPE] 仕様で定義される。
角 速度を検知するジャイロスコープから回転(角度)を得るには、 1 回の積分を行う必要がある。
f ≡ frequency
∫cos(2π×ft)) = (1/(2π×f)) × sin(2π×ft)
ただし、積分はノイズをドリフトに変えることに注意する。上で見るように、積分により 外側に 1/f が出る。つまり、高周波(f)ノイズは積分によって消える。すなわち、ある周波数のノイズは 100 分の 1 に低下するが、非常に低い周波数は増幅される。 これはジャイロスコープが時間とともにドリフトすることを意味する。
したがって、うまく行うには素早く行う必要があり、以下に示すように ∂t を掛けるため、報告された時間差のどのような誤差も、上記のドリフトのように現れる。
θn = θn-1 + ω × ∂t
ここで ω は 角速度を、θ は結果として得られる角度を示す。
ほとんどのジャイロスコープセンサーは、デバイス上の隣接するハードウェアに起因する既知の低周波に対して、 ハードウェア内で何らかのドリフト補償を適用することにより キャリブレーションを行う。
3.3. 磁力計
磁力計は磁場センサーである。 これは、近くに強い磁気的影響がない場合、地球の 磁場を検知することを意味する。 その方向はおおむね北を指すが、真北ではない。 Magnetometer インターフェイスは、[MAGNETOMETER] 仕様で定義される。
前述のように、磁力計は外部からの影響に非常に敏感である。たとえば、わずかに磁化された テーブル上のものなどであり、デバイス内部の他のものにも影響を受ける。ただし、 デバイスメーカーはこれをある程度補償できる。実際には、これらのセンサーは ほとんどの一般的なユースケースではかなりうまく機能する。
周囲で磁化されたものが動き回っていない限り、磁力計の読み取り値は、 上述のように 重力を分離するために 使用できるほど安定している。
磁力計は 3 軸センサーであり、最も強い 磁場を指す 3D ベクトルを与える。これはまた、動作するために 特定のデバイスの向きを強制しないことも意味する。
ただし、デバイスがどのように保持されているかを知るには、重力ベクトルが必要である。 これは、ローパスフィルタリングの場合には少なくとも加速度計を必要とし、 より正確な読み取りが必要な場合にはさらにジャイロスコープを必要とする。 これは 傾き補正と呼ばれる。
磁力計の最も一般的なユースケースは、センサーフュージョンの一部として、 地球平面に対して静止した Orientation Sensor を生成すること、またはコンパスを生成することである。 コンパスは基本的には前者に、地理的位置に応じた偏角の補正を加え、 真北を指すようにしたものである。
4. 高レベルセンサー
上で述べたように、各センサーにはノイズやドリフトなど固有の問題があり、 多くの場合、別のセンサーからの入力を使用した何らかの補償が必要である。 言い換えると、1 つのセンサーだけではあまり正確でない場合でも、 複数の感覚入力の合計ははるかに安定し得る。
残念ながら、センサーは電力を必要とし、センサーの数が多いほど、また測定周波数が高いほど、 消費電力は高くなる。ジャイロスコープは、角 速度を測定するために一定の周波数で振動する必要があるため、 通常は他のセンサーよりも電力を消費すると考えられる。
上記の理由により、タスクを十分に解決するための最小限のセンサーの組を 考慮することが常に重要である。現在の多くのデバイスは、特定の種類のセンサーフュージョンを ハードウェアで行うことができるため、電力および性能の観点から、これらを使用することが ほとんどの場合に理にかなっている。
4.1. 一般的なフュージョンセンサー
以下は、フュージョンセンサーと、それらが通常どのセンサーから構成されるかの一覧である:
| センサー種別 | 基盤となる物理センサー |
|---|---|
| Relative Orientation Sensor | 加速度計、ジャイロスコープ、磁力計を使用してはならない |
| Absolute Orientation Sensor | 加速度計、磁力計、および(存在する場合)ジャイロスコープ |
| Geomagnetic Orientation Sensor | 加速度計、磁力計、ジャイロスコープを使用してはならない |
| Gravity Sensor | 加速度計、ジャイロスコープ |
| Linear Acceleration Sensor | 加速度計、および ジャイロスコープまたは磁力計のいずれか |
4.2. ローパスフィルターおよびハイパスフィルター
先に述べたように、ローパスフィルターおよびハイパスフィルターを使用して ノイズ(高周波または低周波)を除去することが可能である。名前が示すように、これらのフィルターは 低周波または高周波を通過させ、それによって不要な周波数の影響を遮断または最小化する。
4.2.1. ローパスフィルター
ローパスフィルターを作成する一般的な方法は、 最新値の一定割合だけを使用し、残りを既存値から取ることである。ある意味では、 これはフィルターが一般的な値を記憶し、そのため、ほとんどの場合ノイズの結果である 一般的でない値を平滑化することを意味する。既存値の大きな割合を使用するため、 この解法は実際のイベントを登録する際に遅延を導入する。
class LowPassFilterData { constructor(reading, bias) { Object.assign(this, { x: reading.x, y: reading.y, z: reading.z }); this.bias = bias; } update(reading) { this.x = this.x * this.bias + reading.x * (1 - this.bias); this.y = this.y * this.bias + reading.y * (1 - this.bias); this.z = this.z * this.bias + reading.z * (1 - this.bias); } }; const accl = new Accelerometer({ frequency: 20 }); // Isolate gravity with low-pass filter. const filter = new LowPassFilterData(accl, 0.8); accl.onreading = () => { filter.update(accl); // Pass latest values through filter. console.log(`Isolated gravity (${filter.x}, ${filter.y}, ${filter.z})`); } accl.start();
4.2.2. ハイパスフィルター
ハイパスフィルターは ローパス フィルターのように動作するが、高周波のみを通過させる。
これは、ジャイロスコープの読み取りで 時間とともに蓄積するドリフトを取り除くのに有用であり得る。
class HighPassFilterData { constructor(reading, cutoffFrequency) { Object.assign(this, { x: reading.x, y: reading.y, z: reading.z }); this.cutoff = cutoffFrequency; this.timestamp = reading.timestamp; } update(reading) { let dt = reading.timestamp - this.timestamp / 1000; this.timestamp = reading.timestamp; for (let i of ["x", "y", "z"]) { let alpha = this.cutoff / (this.cutoff + dt); this[i] = this[i] + alpha * (reading[i] - this[i]); } } }; const gyro = new Gyroscope({ frequency: 20 }); // Remove drift with a high pass filter. const filter = new HighPassFilterData(gyro, 0.8); gyro.onreading = () => { filter.update(gyro); // Pass latest values through filter. console.log(`Steady gyroscope (${filter.x}, ${filter.y}, ${filter.z})`); } gyro.start();
4.3. 絶対方位センサー
前述のように、絶対方位センサーは、 磁力計の一般的なユースケースの 1 つであり、 地球平面に対して静止した方位(磁場ベクトルおよび 重力ベクトルに固定される)を表すセンサーである。 AbsoluteOrientationSensor インターフェイスは、 [ORIENTATION-SENSOR] 仕様で定義される。
絶対方位センサーは、迷路内のボールパズルのようなゲーム操作や、 ディスプレイを回転させてあらゆる方向を見たいヘッドマウントディスプレイに有用であり得る。
絶対方位センサーの参照フレームは静止しているため、たとえば電話上のドライビングゲームの コントローラーとしては有用ではない。ごくわずかまたはゆっくりであっても、動き回ることを許さず、 運転方向に影響を与えてしまうためである。 (Relative Orientation Sensor を参照)。
Absolute Orientation Sensor の方位ベクトルは、 次の方法で計算できる:
加速度計は 慣性フレーム センサーであるため、デバイスがほぼ静止しており、かつ自由落下していない限り、 重力ベクトルは空に向かって指し、 磁場 ベクトルを地面平面に射影するのに十分なベクトル長がある。
注記, これは磁極では失敗する。 磁場ベクトルが 重力ベクトルとほぼ反対方向を指し、一般に非常に信頼できないためである。
磁場 ベクトルと 重力ベクトル (Gravity Sensor を参照)の 外積を取ることで、右手系の規則を用いて、地面平面上で東を指すベクトルが得られる。
次に、重力ベクトルと、 新しく見つかった東ベクトルとの外積を取ると、結果として得られるベクトルは 地球の 磁場に向かって 北方向を指す。
下の図は、デバイスが静止しており、y 軸が北を向いている場合を表す。 磁力計からの読み取り値は {x: 0, y: 11, z: -16} であり、 加速度計は {x: 0.11, y: 0.07, z: 9.81} の 加速度を報告する。uG は 重力を表す単位ベクトルであり、 uB は 磁場ベクトルを表し、uE = uB × uG で東を指す。uN = uG × uE は 北方向を指す。

これは、Absolute Orientation Sensor が 磁力計と 加速度計のフュージョンセンサーであり、さらに、よりよく分離された 重力のために潜在的には ジャイロスコープも含むことを意味する (Gravity Sensor を参照)。
4.4. 地磁気方位センサー
地磁気方位センサーは、 Absolute Orientation Sensor に似ているが、 ジャイロスコープを使用しないため、 より少ない電力を使用する。これはまた、揺れや移動に対してより敏感であることも意味する。
Geomagnetic Orientation Sensor の主なユースケースは、 コンパスを作成すること、またはマッピングアプリケーション内でコンパス方向を使用することであるため、 人々は通常このようなユースケースではデバイスを安定して保持するので、これは大きな問題ではない。
実際の方位(N, S, E, W)は、現在の地理的位置から計算された ローカルな偏角補償で回転ベクトルを調整することにより得られる。
センサーは、歩行時などにより安定した方位を得るために 加速度計を使用するため、 回転ベクトルは(加速度計から 分離された)重力ベクトルに垂直な平面に射影される。 これはおおむね地面平面を表す。これはまた、 重力ベクトルの実際の向きに 関心がある場合は、代わりに 磁力計を直接使用することを意味する。
4.5. 相対方位センサー
ほとんどのセンサーハブでは、重力は ジャイロスコープを使用して 加速度計から分離され、 線形加速度は、 加速度計の値から分離された 重力を取り除くことにより分離される。
これにより、ローパスフィルターおよびハイパスフィルターが導入する遅延を避けることができる。
これを行う 1 つの方法は、カルマンフィルターまたは 相補フィルターを使用することであり、これが Relative Orientation Sensorにつながる。相補フィルターはかなり良い結果を生み、 ハードウェアで実装しやすいため、これは一般的な解決策である。
4.5.1. 相補フィルター
相補 フィルターは、 ローパスフィルターと ハイパスフィルターを 1 つにしたものと考えることができ、 ジャイロスコープの値を 加速度計 の値で補完する:
θn = α × (θn-1 + ω × ∂t) + (1.0 - α) × a
ここで、α は重み定数、a は 加速度計からの加速度、ω は 角 速度であり、これは ジャイロスコープからの値である。 ∂t は測定間の時間である。
α の一般的な値は 0.98 であり、これは重みの 98% が ジャイロスコープ測定値に置かれることを意味する。
ジャイロスコープは 角速度を測定するため、時間差を掛けることで 角度の変化が得られる。この変化は常に現在のデバイス位置に対して相対的に計算されるため、 加速度計を使用する必要がある。加速度計には 重力が含まれるため、 これを地面平面に合わせてキャリブレーションできる。
加速度計からの値は、方位(alpha、z 周りの回転)について 何の情報ももたらさないため、alpha 成分には含めない。一方、 加速度計は (重力により)デバイスが x 軸および y 軸周り(beta および gamma)で どのように保持されているかについての情報を提供する。
動きがない、または少ない場合、加速度計の読み取りから得られるベクトルは、 ジャイロスコープよりも多く、(alpha, beta, gamma) 角度に寄与する。
安定した 加速度計からの値は 重力ベクトルを表し、 z 成分を alpha に含めないため、その結果として方位は ジャイロスコープに従うだけで安定する。 しかし、方位の原点は開始時のデバイス位置に依存するため、これは デバイス相対方位センサーである。
const options = { frequency: 50 }; const accl = new Accelerometer(options); const gyro = new Gyroscope(options); let timestamp = null; let alpha = beta = gamma = 0; const bias = 0.98; gyro.onreading = () => { let dt = timestamp ? (gyro.timestamp - timestamp) / 1000 : 0; timestamp = gyro.timestamp; // Treat the acceleration vector as an orientation vector by normalizing it. // Keep in mind that the if the device is flipped, the vector will just be // pointing in the other direction, so we have no way to know from the // accelerometer data which way the device is oriented. const norm = Math.sqrt(accl.x ** 2 + accl.y ** 2 + accl.z ** 2); // As we only can cover half (PI rad) of the full spectrum (2*PI rad) we multiply // the unit vector with values from [-1, 1] with PI/2, covering [-PI/2, PI/2]. const scale = Math.PI / 2; alpha = alpha + gyro.z * dt; beta = bias * (beta + gyro.x * dt) + (1.0 - bias) * (accl.x * scale / norm); gamma = bias * (gamma + gyro.y * dt) + (1.0 - bias) * (accl.y * -scale / norm); // Do something with Euler angles (alpha, beta, gamma). }; accl.start(); gyro.start();
上記の例から、alpha が初期の方位向きを表していることが分かる。 また、この方位は ジャイロスコープに 基づくため、時間とともにドリフトし得ることも分かっている。
状況によっては、方位を現在の位置へ向かってドリフトさせたい場合がある。 これは、仮想現実環境内のコントローラーに有用であり得る。たとえば、 車にコントローラーの方位に従わせたいが、プレイ中に自分が動いたり回ったりする場合である。 これは実際の車を運転するのとほぼ同じように機能する。
上記の 1 行を変更すると、それを実現できる。
const zeroBias = 0.02; alpha = (1 - zeroBias) * (alpha + gyro.z * dt);
上記では、alpha の 2% が値 0 で構成される。したがって、デバイスがほぼ安定して保持されている場合、 方位は 0 に向かって移動する。これは、周囲に従って配置されるのではなく、 現在のデバイス位置に合わせて調整されることを意味する。
この例は、手動フュージョンが場合によってどれほど有用になり得るかを示している。
4.6. 重力および線形加速度センサー
上で使用した 相補 フィルターは 重力の分離にかなり優れており、 そのため、ほとんどのセンサーハブは ジャイロスコープを使用して 加速度計から重力を分離し、 線形 加速度は、加速度計の値から分離された 重力を取り除くことにより分離される。
これはまた、ほとんどのセンサーハブによって公開される Linear Acceleration Sensor および Gravity Sensor は、 ほぼ間違いなくフュージョンセンサーであることを意味する。
重力は、 linear acceleration sensor から 磁力計を使用して取り除くこともできる。 磁場ベクトルがほぼ安定しているためである。
LinearAccelerationSensor インターフェイスおよび GravitySensor インターフェイスは、 [ACCELEROMETER] 仕様で定義される。
注記, 重力は動きの周波数に応じて変化する。 すなわち、自由落下では落下方向で 0 になる。そのため、 揺れを検出しようとする場合、線形 加速度はかなり不正確になり得ることを想像できるので、その点に留意すること。
4.7. ユースケースと要件
高度なモーションセンサーのユースケースでは、正確なセンサー読み取り値、 ハードウェアセンサーが動作する高いサンプリングレート、および特定のアプリケーションにとって 望ましい読み取り配信レートが要件となる場合がある。
モーションセンサーは、次のようなさまざまな高度なユースケースに使用できる:
-
仮想現実および拡張現実の HMD トラッキング [HMDTRACKING]
-
センサー支援による屋内マッピングおよびナビゲーション [INDOORNAV], [IPIN]
-
写真および動画撮影の安定化 [ROLLSTABILIZER], [VIDEOSTABILIZER]
-
高精度の読み取り値を伴う高周波サンプリングレートを必要とするゲーム。
-
3D スキャン [3DSCANNING]
-
高度なジェスチャー認識 [MEMSGESTURES]
-
歩数計測およびその他の身体活動の監視 [PHYSMON]
モーションセンサーを使用するゲームまたは UI アプリケーションにおける一般的な要件は、 レンダリングされる各フレームごとに新しいセンサー読み取り値を持つことである。 この場合、より高いサンプリングレートはレイテンシーを低減し、 それによりユーザー体験を改善する。
仮想現実 HMD トラッキングの場合、センサーは非常に高いサンプリングレート (最大数 kHz)で動作し、75-120Hz のリフレッシュレートでレンダリングされる各フレームに対して 最新のセンサー読み取り値を提供することにより、motion-to-photon レイテンシーを最小化することがある。
屋内ナビゲーションまたは非リアルタイムの動画(画像)安定化アプリケーションは、 高いサンプリングレート(80-100Hz)で高精度のセンサー読み取り値を収集することから恩恵を受け得る。 それにより、データ処理アルゴリズムが正確な結果を提供するために十分なサンプルを持てるためである。