重力センサーは加速度センサーと取り扱いが似ているセンサーで、データ構造は加速度センサーと全く同じです。加速度センサーがそれぞれの方向に対する加速度だったのに対し、重力センサーはそれぞれの方向に対する重力が渡されてきます。
重力センサーは重力加速度に特化した加速度センサーとも捉えることができます。このセンサーでは、デバイスを左右にスナップさせたとしても、センサーが通知してくる値に影響を与えません。また、X軸、Y軸、Z軸のベクトルの合計は重力加速度と一致するため、デバイスの姿勢を把握することも容易です。
余談ですが、重力センサーの通知してくる値を加速度センサーの実際の値を取得する際に使用している重力加速度を取り除くメソッドで変換すると、全ての軸に対する加速度が0になります。
さて、サンプルではX軸、Y軸の重力加速度に係数を与え、デバイスを傾けた方向にロケットが滑り落ちるようにしています。
@Override
void repaint(Canvas canvas, Paint paint) {
if (canvas != null) {
// 加速度にメリハリを
float xg = mValues[0] * Math.abs(mValues[0]);
float yg = mValues[1] * Math.abs(mValues[1]);
mX -= xg;
mY += yg;
// 過去5回分の平均を算出
float dx = 0, dy = 0;
for (int i = 0; i < mPrevX.length; i++) {
dx += mPrevX[i];
dy += mPrevY[i];
}
dx = dx / mPrevX.length - mX;
dy = dy / mPrevY.length - mY;
// 移動距離が多いなら噴射
boolean hasFire = Math.sqrt(dx * dx + dy * dy) > 100;
// ロケットの回転角を算出
float radian = (float) Math.atan2(dy, dx);
float degrees = (float) (radian * 180 / Math.PI) - 90;
Bitmap bitmap = hasFire ? mFiring : mPlain;
// 各種描画
canvas.save();
canvas.rotate(degrees, mX + bitmap.getWidth() / 2,
mY + bitmap.getHeight() / 2);
canvas.drawBitmap(bitmap, mX, mY, null);
canvas.restore();
canvas.drawText("x:" + mValues[0], 0, paint.getTextSize() * 1,
paint);
canvas.drawText("y:" + mValues[1], 0, paint.getTextSize() * 2,
paint);
canvas.drawText("z:" + mValues[2], 0, paint.getTextSize() * 3,
paint);
// 履歴保持
mPrevX[mCount] = mX;
mPrevY[mCount] = mY;
mCount++;
if (mCount == mPrevX.length) {
mCount = 0;
}
}
}
どのような係数を与えるかはアプリ次第です。本サンプルでは加速度を2乗して、加速度が速い時により速くなるように演出しています。また一方で、突発的な加速度の変化を吸収する“あそび”も設けてあり、過去の5回分の平均加速度からロケットの移動距離を導き出すようにしています。
ロケットの移動速度が速い場合は噴射しているビットマップを描画するように制御しています。ロケットの移動に応じてビットマップを回転させるための回転角も計算しています。
加速度センサーと違い、常に重力方向に重力加速度が働いているという点が重力センサーを差別化するポイントでしょう(正確には加速度センサーも重力加速度が働いていますが)。このセンサーを利用したボールを転がすゲームはGoogle Playストアで幾つか見つかりますね。
ジャイロスコープはX軸、Y軸、Z軸の回転速度を取得可能なセンサーです。
回転速度の単位はrad/sです。ジャイロスコープの値の意味は以下の通りです。
このセンサーは姿勢の変化を検出するのに適しています。
デモでは他のサンプルと同様、簡単のためにX軸とY軸の回転速度から、描画オブジェクトの座標変換を行っています。
@Override
void repaint(Canvas canvas, Paint paint) {
if (mPoints != null) {
// X軸とY軸の回転速度を取得
float dx = mValues[1];
float dy = mValues[0];
// 係数を掛けて座標変換に用いる
double theta = dy * 0.1;
double phi = dx * 0.1;
rotate(theta, phi);
if (canvas != null) {
canvas.drawText("x:" + mValues[0], 0,
paint.getTextSize() * 1, paint);
canvas.drawText("y:" + mValues[1], 0,
paint.getTextSize() * 2, paint);
canvas.drawText("z:" + mValues[2], 0,
paint.getTextSize() * 3, paint);
// 描画時に座標位置に合わせて透明度を計算
for (int i = 0; i < mPoints.length; i++) {
float x = mPoints[i][1] * mScale * 4 + mRadius;
float y = mPoints[i][0] * mScale * 4 + mRadius;
float ratio = Math.abs((mPoints[i][2] - 1) / 3);
int color = Color.argb((int) (ratio * 0xff), 0xff,
0xff, 0xff);
paint.setColor(color);
canvas.drawRect(x, y, x + 5, y + 5, paint);
}
}
}
}
動画の通りですが、このデモにはおまけとしてタッチで座標変換が行える機能もついています。
さて、ジャイロスコープの回転速度ですが、このサンプルでは「0.1」という係数を掛けてコード内で利用しています。回転速度をどのように用いるかによるのですが、机上に静止させている状態でも通知される値は微動し、よほどセンシティブなアプリではないなら、今回のサンプルのように係数を掛けるなり、ある一定の速度以下であれば無視するなどの対応を行うのが良さそうです。
今回はセンサーの中でも系統が似ていて、スマートフォンやウェアラブル端末で使用頻度が高そうな加速度センサー、重力センサー、ジャイロスコープを取り上げましたが、冒頭に記載した通り、Androidには多種多様なセンサーが存在します。
次回は、Android 4.4で追加されたステップカウンターなどのセンサーを取り上げる予定ですので、お楽しみに。
頭脳放談:第160回 ウェアラブルによるスマホ補完計画始動
ウェアラブルデバイスの実務参入は進むか?:業務向けGoogle Glassアプリ開発促進フォーラム「Glass at Work」開設
テクノロジは人の考え方も変える:「ウェアラブル」の先にあるのは「トランスペアレント・コンピューティング」
「俺たちのJavaは、まだまだこれからだ」未来の鍵はInternet of Thingsにあり?〜JavaOne 2013まとめレポート(前編)
業務アプリInsider 読者調査レポート:業務アプリにおける次世代テクノロジの3大トレンド
業務アプリInsider×未来テクノロジ:業務アプリはもうこれ以上、進化できないのか? ―― スマートアグリカルチャーに学ぼうCopyright © ITmedia, Inc. All Rights Reserved.