Android プラットフォームには、デバイスの動きを監視できるセンサーがいくつか用意されています。
センサーのアーキテクチャは、センサーの種類によって異なります。
- 重力、リニア加速度、回転ベクトル、大きなモーション、歩数計、歩行検出機能の各センサーは、ハードウェア ベースまたはソフトウェア ベースのいずれかです。
- 加速度計センサーとジャイロスコープ センサーは常にハードウェア ベースです。
ほとんどの Android 搭載デバイスには加速度計が搭載されており、ジャイロスコープを搭載しているデバイスも増えています。ソフトウェア ベースのセンサーは、データを取得するために 1 つ以上のハードウェア センサーに依存することが多いため、可用性が変動しやすくなります。デバイスによっては、これらのソフトウェア ベースのセンサーは、加速度計と磁力計、またはジャイロスコープからデータを取得できます。
モーション センサーは、傾斜、シェイク、回転、スウィングなどのデバイスの動きをモニタリングするのに役立ちます。通常、動きはユーザーの直接的な入力(ゲームで車を運転するユーザーや、ゲームでボールを操作するユーザーなど)を反映したものですが、デバイスが置かれている物理環境を反映したもの(車を運転しているときに一緒に動くなど)であることもあります。前者の場合は、デバイスの基準フレームまたはアプリの基準フレームに対する動きをモニタリングし、後者の場合は、世界の基準フレームに対する動きをモニタリングします。モーション センサーは通常、単独でデバイスの位置をモニタリングするために使用されることはありませんが、地磁気センサーなどの他のセンサーと組み合わせて、世界座標系に対するデバイスの位置を特定するために使用できます(詳しくは、位置センサーをご覧ください)。
すべてのモーション センサーは、SensorEvent
ごとにセンサー値の多次元配列を返します。たとえば、1 回のセンサー イベントで、加速度計は 3 つの座標軸の加速度データ、ジャイロスコープは 3 つの座標軸の回転速度データを返します。これらのデータ値は、他の SensorEvent
パラメータとともに float
配列(values
)で返されます。表 1 に、Android プラットフォームで利用できるモーション センサーをまとめます。
表 1. Android プラットフォームでサポートされているモーション センサー
センサー | センサー イベント データ | 説明 | 測定単位 |
---|---|---|---|
TYPE_ACCELEROMETER |
SensorEvent.values[0] |
x 軸方向の加速度(重力を含む)。 | m/s2 |
SensorEvent.values[1] |
y 軸方向の加速度(重力を含む)。 | ||
SensorEvent.values[2] |
Z 軸方向の加速度(重力を含む)。 | ||
TYPE_ACCELEROMETER_UNCALIBRATED |
SensorEvent.values[0] |
バイアス補正なしで X 軸に沿って測定された加速度。 | m/s2 |
SensorEvent.values[1] |
バイアス補正なしで Y 軸に沿って測定された加速度。 | ||
SensorEvent.values[2] |
バイアス補正なしで Z 軸に沿って測定された加速度。 | ||
SensorEvent.values[3] |
X 軸方向の加速度の測定値(バイアス補正の推定値を含む)。 | ||
SensorEvent.values[4] |
推定バイアス補正を適用した Y 軸方向の加速度。 | ||
SensorEvent.values[5] |
推定バイアス補正による Z 軸方向の測定加速度。 | ||
TYPE_GRAVITY |
SensorEvent.values[0] |
X 軸に沿った重力。 | m/s2 |
SensorEvent.values[1] |
Y 軸に沿った重力。 | ||
SensorEvent.values[2] |
Z 軸に沿った重力。 | ||
TYPE_GYROSCOPE |
SensorEvent.values[0] |
X 軸を中心とした回転速度。 | rad/s |
SensorEvent.values[1] |
Y 軸を中心とした回転速度。 | ||
SensorEvent.values[2] |
Z 軸を中心とした回転速度。 | ||
TYPE_GYROSCOPE_UNCALIBRATED |
SensorEvent.values[0] |
x 軸を中心とした回転速度(ブレ補正なし)。 | rad/s |
SensorEvent.values[1] |
Y 軸を中心とした回転速度(ブレ補正なし)。 | ||
SensorEvent.values[2] |
z 軸を中心とした回転速度(ブレ補正なし)。 | ||
SensorEvent.values[3] |
x 軸を中心とした推定ブレ。 | ||
SensorEvent.values[4] |
Y 軸を中心とした推定ブレ。 | ||
SensorEvent.values[5] |
Z 軸を中心とした推定ブレ。 | ||
TYPE_LINEAR_ACCELERATION |
SensorEvent.values[0] |
x 軸方向の加速力(重力を除く)。 | m/s2 |
SensorEvent.values[1] |
Y 軸方向の加速力(重力を除く)。 | ||
SensorEvent.values[2] |
Z 軸方向の加速力(重力を除く)。 | ||
TYPE_ROTATION_VECTOR |
SensorEvent.values[0] |
X 軸に沿った回転ベクトルの成分(x * sin(θ/2))。 | 単位なし |
SensorEvent.values[1] |
Y 軸に沿った回転ベクトルのコンポーネント(y * sin(θ/2))。 | ||
SensorEvent.values[2] |
Z 軸に沿った回転ベクトルの成分(z * sin(θ/2))。 | ||
SensorEvent.values[3] |
回転ベクトルのスカラー成分(cos(θ/2))。1 | ||
TYPE_SIGNIFICANT_MOTION |
なし | 該当なし | なし |
TYPE_STEP_COUNTER |
SensorEvent.values[0] |
センサーが有効にされている間に最後に再起動した時点からユーザーが歩いた歩数。 | 手順 |
TYPE_STEP_DETECTOR |
なし | 該当なし | なし |
1 スカラー コンポーネントは省略可能な値です。
回転ベクトル センサーと重力センサーは、モーションの検出とモニタリングに最もよく使用されるセンサーです。回転ベクトル センサーは特に汎用性が高く、ジェスチャーの検出、角度変化のモニタリング、相対的な向きの変化のモニタリングなど、モーション関連の幅広いタスクに使用できます。たとえば、ゲーム、拡張現実アプリ、2 次元または 3 次元のコンパス、カメラ安定化アプリを開発している場合は、回転ベクトル センサーが最適です。ほとんどの場合、これらのセンサーを使用する方が、加速度計と地磁気センサーまたは方位センサーを使用するよりも優れています。
Android オープンソース プロジェクトのセンサー
Android オープンソース プロジェクト(AOSP)は、重力センサー、リニア加速度センサー、回転ベクトル センサーという 3 つのソフトウェアベースのモーション センサーを提供します。これらのセンサーは Android 4.0 で更新され、安定性とパフォーマンスを向上させるために(他のセンサーに加えて)デバイスのジャイロスコープを使用するようになりました。これらのセンサーを試す場合は、getVendor()
メソッドと getVersion()
メソッドを使用して識別できます(ベンダーは Google LLC、バージョン番号は 3)。Android システムでは、これらの 3 つのセンサーはセカンダリ センサーと見なされるため、ベンダーとバージョン番号でこれらのセンサーを識別する必要があります。たとえば、デバイス メーカーが独自の重力センサーを提供する場合、AOSP の重力センサーはセカンダリ重力センサーとして表示されます。これらの 3 つのセンサーはすべてジャイロスコープに依存しています。デバイスにジャイロスコープがない場合、これらのセンサーは表示されず、使用できません。
重力センサーを使用する
重力センサーは、重力の方向と大きさを示す 3 次元ベクトルを提供します。通常、このセンサーは空間におけるデバイスの相対的な向きを判断するために使用されます。次のコードは、デフォルトの重力センサーのインスタンスを取得する方法を示しています。
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
単位は加速度センサーで使用される単位(m/s2)と同じで、座標系は加速度センサーで使用される座標系と同じです。
注: デバイスが静止しているときは、重力センサーの出力が加速度計の出力と同じであることが必要です。
線形加速度計を使用する
直線加速度センサーは、重力を除いた各デバイス軸に沿った加速度を表す 3 次元ベクトルを提供します。この値を使用してジェスチャー検出を行うことができます。この値は、推測航法を使用する慣性航法システムの入力としても使用できます。次のコードは、デフォルトの線形加速度センサーのインスタンスを取得する方法を示しています。
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
このセンサーは、概念的には次の関係に従って加速度データを提供します。
linear acceleration = acceleration - acceleration due to gravity
通常、このセンサーは重力の影響を受けずに加速度データを取得する場合に使用します。たとえば、このセンサーを使用して、車の速度を確認できます。線形加速度センサーには常にオフセットがあり、削除する必要があります。最も簡単な方法は、アプリケーションにキャリブレーション ステップを組み込むことです。キャリブレーション中に、ユーザーにデバイスをテーブルに置くよう指示し、3 つの軸すべてのオフセットを読み取ることができます。このオフセットを加速度センサーの直接読み取り値から差し引くと、実際の直線加速度が得られます。
センサーの座標系は加速度センサーで使用されているものと同じで、測定単位(m/s2)も同じです。
回転ベクトル センサーを使用する
回転ベクトルは、デバイスの向きを角度と軸の組み合わせとして表します。デバイスは軸(x、y、z)を中心に角度 θ だけ回転しています。次のコードは、デフォルトの回転ベクトル センサーのインスタンスを取得する方法を示しています。
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
回転ベクトルの 3 つの要素は次のように表されます。

ここで、回転ベクトルの大きさは sin(θ/2) に等しく、回転ベクトルの方向は回転軸の方向と等しくなります。

図 1. 回転ベクトル センサーで使用される座標系。
回転ベクトルの 3 つの要素は、単位四元数の最後の 3 つのコンポーネント(cos(θ/2)、x*sin(θ/2)、y*sin(θ/2)、z*sin(θ/2))と等しくなります。回転ベクトルの要素は単位なしです。x 軸、y 軸、z 軸は、加速度センサーと同じ方法で定義されます。基準座標系は、直接正規直交基底として定義されます(図 1 を参照)。この座標系には次の特徴があります。
- X はベクトル積 Y x Z として定義されます。デバイスの現在地における地面に対して接線の方向であり、ほぼ東を指しています。
- Y は、デバイスの現在地における地面に対して接線の方向であり、地磁気の北極を指しています。
- Z は空を指し、地面に対して垂直である。
回転ベクトル センサーの使用方法を示すサンプル アプリケーションについては、 RotationVectorDemo.java をご覧ください。
重要なモーション センサーを使用する
大きなモーション センサーは、大きなモーションが検出されるたびにイベントをトリガーし、その後自身を無効にします。大きなモーションとは、ユーザーの位置情報の変化につながる可能性がある動き(歩行、自転車、走行中の自動車の座席に座っているなど)のことです。次のコードは、デフォルトの重大なモーション センサーのインスタンスを取得し、イベント リスナーを登録する方法を示しています。
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val mSensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION) val triggerEventListener = object : TriggerEventListener() { override fun onTrigger(event: TriggerEvent?) { // Do work } } mSensor?.also { sensor -> sensorManager.requestTriggerSensor(triggerEventListener, sensor) }
Java
private SensorManager sensorManager; private Sensor sensor; private TriggerEventListener triggerEventListener; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); triggerEventListener = new TriggerEventListener() { @Override public void onTrigger(TriggerEvent event) { // Do work } }; sensorManager.requestTriggerSensor(triggerEventListener, mSensor);
詳しくは TriggerEventListener
をご覧ください。
歩数計センサーを使用する
歩数計センサーは、センサーが有効になっている間に最後に再起動した時点からユーザーが歩いた歩数を報告します。歩数計は、歩行検出機能センサーよりもレイテンシは大きい(最大 10 秒)ものの、精度は高くなります。
注: Android 10(API レベル 29)以上を搭載したデバイスでアプリがこのセンサーを使用するには、ACTIVITY_RECOGNITION
権限を宣言する必要があります。
次のコードは、デフォルトの歩数計センサーのインスタンスを取得する方法を示しています。
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
アプリを実行しているデバイスのバッテリーを節約するには、JobScheduler
クラスを使用して、特定のインターバルで歩数計センサーから現在の値を取得する必要があります。アプリの種類によってセンサーの読み取り間隔は異なりますが、アプリがセンサーからのリアルタイム データを必要としない限り、この間隔はできるだけ長くする必要があります。
歩行検出センサーを使用する
歩行検出機能センサーは、ユーザーが 1 歩歩くたびにイベントをトリガーします。レイテンシは 2 秒未満になることが想定されます。
注: Android 10(API レベル 29)以上を搭載したデバイスでアプリがこのセンサーを使用するには、ACTIVITY_RECOGNITION
権限を宣言する必要があります。
次のコードは、デフォルトの歩数検出センサーのインスタンスを取得する方法を示しています。
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
生データを操作する
次のセンサーは、デバイスに適用される線形力と回転力に関する未加工のデータをアプリに提供します。これらのセンサーの値を効果的に使用するには、重力などの環境要因をフィルタで除去する必要があります。ノイズを減らすために、値の傾向に平滑化アルゴリズムを適用する必要がある場合もあります。
加速度計を使用する
加速度センサーは、重力を含むデバイスにかかる加速度を測定します。次のコードは、デフォルトの加速度センサーのインスタンスを取得する方法を示しています。
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
注: アプリのターゲットが Android 12(API レベル 31)以降の場合、このセンサーはレート制限されます。
概念的には、加速度センサーは、次の関係を使用してセンサー自体に適用される力(Fs)を測定することで、デバイスに適用される加速度(Ad)を決定します。

ただし、重力は常に次の関係に従って測定された加速度に影響します。

このため、デバイスがテーブルの上に置かれている場合(加速度がない場合)、加速度計は g = 9.81 m/s2 の大きさを示します。同様に、デバイスが自由落下している場合、9.81 m/s2 で地面に向かって急速に加速しているため、加速度計は g = 0 m/s2 の大きさを読み取ります。したがって、デバイスの実際の加速度を測定するには、加速度計のデータから重力の寄与を取り除く必要があります。これは、ハイパス フィルタを適用することで実現できます。逆に、ローパス フィルタを使用して重力を分離することもできます。次の例は、この方法を示しています。
Kotlin
override fun onSensorChanged(event: SensorEvent) { // In this example, alpha is calculated as t / (t + dT), // where t is the low-pass filter's time-constant and // dT is the event delivery rate. val alpha: Float = 0.8f // Isolate the force of gravity with the low-pass filter. gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0] gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1] gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2] // Remove the gravity contribution with the high-pass filter. linear_acceleration[0] = event.values[0] - gravity[0] linear_acceleration[1] = event.values[1] - gravity[1] linear_acceleration[2] = event.values[2] - gravity[2] }
Java
public void onSensorChanged(SensorEvent event){ // In this example, alpha is calculated as t / (t + dT), // where t is the low-pass filter's time-constant and // dT is the event delivery rate. final float alpha = 0.8; // Isolate the force of gravity with the low-pass filter. gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]; gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]; gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]; // Remove the gravity contribution with the high-pass filter. linear_acceleration[0] = event.values[0] - gravity[0]; linear_acceleration[1] = event.values[1] - gravity[1]; linear_acceleration[2] = event.values[2] - gravity[2]; }
注: センサーデータをフィルタするには、さまざまな手法を使用できます。上記のコードサンプルでは、単純なフィルタ定数(アルファ)を使用してローパス フィルタを作成しています。このフィルタ定数は、フィルタがセンサー イベントに追加するレイテンシの概算を表す時間定数(t)と、センサーのイベント配信率(dt)から導出されます。このコードサンプルでは、デモ用にアルファ値 0.8 を使用しています。このフィルタリング方法を使用する場合は、別のアルファ値を選択する必要がある場合があります。
加速度計は標準のセンサー座標系を使用します。実際には、デバイスが自然な向きでテーブルに平らに置かれている場合、次の条件が適用されます。
- デバイスの左側を押して右に移動させると、x 加速度の値は正になります。
- デバイスを下方向に押すと(自分から離れる方向に動かすと)、y 加速度の値は正になります。
- デバイスを A m/s2 の加速度で空に向けて押すと、z 軸の加速度の値は A + 9.81 になります。これは、デバイスの加速度(+A m/s2)から重力(-9.81 m/s2)を差し引いた値に相当します。
- 静止しているデバイスの加速度の値は +9.81 になります。これは、デバイスの加速度(0 m/s2)から重力(-9.81 m/s2)を差し引いた値に相当します。
一般に、デバイスの動きをモニタリングする場合は、加速度計を使用することをおすすめします。Android 搭載のハンドセットとタブレットのほぼすべてに加速度計が搭載されており、他のモーション センサーよりも約 10 分の 1 の電力しか消費しません。欠点の 1 つは、重力を排除してノイズを低減するために、ローパス フィルタとハイパス フィルタを実装する必要があることです。
ジャイロスコープを使用する
ジャイロスコープは、デバイスの x 軸、y 軸、z 軸に対する回転速度を rad/s 単位で測定します。次のコードは、デフォルトのジャイロスコープのインスタンスを取得する方法を示しています。
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
注: アプリのターゲットが Android 12(API レベル 31)以降の場合、このセンサーはレート制限されます。
センサーの座標系は、加速度センサーで使用されるものと同じです。回転は反時計回りで正の値に設定されます。つまり、原点に配置されたデバイスを x 軸、y 軸、または z 軸上の正の位置から見ているオブザーバーは、デバイスが反時計回りに回転しているように見える場合に正の回転を報告します。これは、正の回転の標準的な数学的定義であり、方向センサーで使用されるロールの定義とは異なります。
通常、ジャイロスコープの出力は時間とともに統合され、タイムステップでの角度の変化を表す回転が計算されます。次に例を示します。
Kotlin
// Create a constant to convert nanoseconds to seconds. private val NS2S = 1.0f / 1000000000.0f private val deltaRotationVector = FloatArray(4) { 0f } private var timestamp: Float = 0f override fun onSensorChanged(event: SensorEvent?) { // This timestep's delta rotation to be multiplied by the current rotation // after computing it from the gyro sample data. if (timestamp != 0f && event != null) { val dT = (event.timestamp - timestamp) * NS2S // Axis of the rotation sample, not normalized yet. var axisX: Float = event.values[0] var axisY: Float = event.values[1] var axisZ: Float = event.values[2] // Calculate the angular speed of the sample val omegaMagnitude: Float = sqrt(axisX * axisX + axisY * axisY + axisZ * axisZ) // Normalize the rotation vector if it's big enough to get the axis // (that is, EPSILON should represent your maximum allowable margin of error) if (omegaMagnitude > EPSILON) { axisX /= omegaMagnitude axisY /= omegaMagnitude axisZ /= omegaMagnitude } // Integrate around this axis with the angular speed by the timestep // in order to get a delta rotation from this sample over the timestep // We will convert this axis-angle representation of the delta rotation // into a quaternion before turning it into the rotation matrix. val thetaOverTwo: Float = omegaMagnitude * dT / 2.0f val sinThetaOverTwo: Float = sin(thetaOverTwo) val cosThetaOverTwo: Float = cos(thetaOverTwo) deltaRotationVector[0] = sinThetaOverTwo * axisX deltaRotationVector[1] = sinThetaOverTwo * axisY deltaRotationVector[2] = sinThetaOverTwo * axisZ deltaRotationVector[3] = cosThetaOverTwo } timestamp = event?.timestamp?.toFloat() ?: 0f val deltaRotationMatrix = FloatArray(9) { 0f } SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector); // User code should concatenate the delta rotation we computed with the current rotation // in order to get the updated rotation. // rotationCurrent = rotationCurrent * deltaRotationMatrix; }
Java
// Create a constant to convert nanoseconds to seconds. private static final float NS2S = 1.0f / 1000000000.0f; private final float[] deltaRotationVector = new float[4](); private float timestamp; public void onSensorChanged(SensorEvent event) { // This timestep's delta rotation to be multiplied by the current rotation // after computing it from the gyro sample data. if (timestamp != 0) { final float dT = (event.timestamp - timestamp) * NS2S; // Axis of the rotation sample, not normalized yet. float axisX = event.values[0]; float axisY = event.values[1]; float axisZ = event.values[2]; // Calculate the angular speed of the sample float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ); // Normalize the rotation vector if it's big enough to get the axis // (that is, EPSILON should represent your maximum allowable margin of error) if (omegaMagnitude > EPSILON) { axisX /= omegaMagnitude; axisY /= omegaMagnitude; axisZ /= omegaMagnitude; } // Integrate around this axis with the angular speed by the timestep // in order to get a delta rotation from this sample over the timestep // We will convert this axis-angle representation of the delta rotation // into a quaternion before turning it into the rotation matrix. float thetaOverTwo = omegaMagnitude * dT / 2.0f; float sinThetaOverTwo = sin(thetaOverTwo); float cosThetaOverTwo = cos(thetaOverTwo); deltaRotationVector[0] = sinThetaOverTwo * axisX; deltaRotationVector[1] = sinThetaOverTwo * axisY; deltaRotationVector[2] = sinThetaOverTwo * axisZ; deltaRotationVector[3] = cosThetaOverTwo; } timestamp = event.timestamp; float[] deltaRotationMatrix = new float[9]; SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector); // User code should concatenate the delta rotation we computed with the current rotation // in order to get the updated rotation. // rotationCurrent = rotationCurrent * deltaRotationMatrix; }
標準ジャイロスコープは、ノイズやドリフト(バイアス)のフィルタリングや補正を行わずに、生の回転データを提供します。実際には、ジャイロスコープのノイズとドリフトによって誤差が生じるため、補正する必要があります。通常、ドリフト(バイアス)とノイズは、重力センサーや加速度計などの他のセンサーをモニタリングすることで特定します。
未調整のジャイロスコープを使用する
未調整のジャイロスコープは ジャイロスコープに似ていますが、回転速度にジャイロ ドリフト補正が適用されない点が異なります。回転速度には、工場での調整と温度補正が引き続き適用されます。未調整のジャイロスコープは、後処理や向きデータの統合に役立ちます。一般に、gyroscope_event.values[0]
は uncalibrated_gyroscope_event.values[0] - uncalibrated_gyroscope_event.values[3]
に近い値になります。つまり、
calibrated_x ~= uncalibrated_x - bias_estimate_x
注: 未調整のセンサーはより多くの未加工の結果を提示し、バイアスが含まれることもありますが、測定値には調整によって適用される修正からのジャンプが少なくなります。一部のアプリは、これらの未調整の結果を、よりスムーズで信頼性の高いものとして優先的に扱う場合があります。たとえば、アプリケーションが独自のセンサー フュージョンを実行しようとしている場合は、調整によって実際に結果に偏りが生じる可能性があります。
未調整のジャイロスコープは、回転速度に加えて、各軸を中心とする推定ドリフトも提供します。次のコードは、デフォルトの未調整ジャイロスコープのインスタンスを取得する方法を示しています。
Kotlin
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED)
Java
private SensorManager sensorManager; private Sensor sensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED);
その他のコードサンプル
BatchStepSensor サンプルでは、このページで説明した API の使用例がさらに紹介されています。