連載
» 2014年05月22日 18時00分 公開

Androidで動く携帯Javaアプリ作成入門(51):ウェアラブル時代に見直したいAndroidの加速度/重力センサー、ジャイロスコープ (3/3)

[緒方聡,株式会社イーフロー]
前のページへ 1|2|3       

X軸、Y軸、Z軸に対する重力を計る「重力センサー」

 重力センサーは加速度センサーと取り扱いが似ているセンサーで、データ構造は加速度センサーと全く同じです。加速度センサーがそれぞれの方向に対する加速度だったのに対し、重力センサーはそれぞれの方向に対する重力が渡されてきます。

重力センサーのサンプルアプリを動かす動画(クリックすると再生が始まります)

 重力センサーは重力加速度に特化した加速度センサーとも捉えることができます。このセンサーでは、デバイスを左右にスナップさせたとしても、センサーが通知してくる値に影響を与えません。また、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軸の回転速度を取得する「ジャイロスコープ」

 ジャイロスコープはX軸、Y軸、Z軸の回転速度を取得可能なセンサーです。

ジャイロスコープのサンプルアプリを動かす動画(クリックすると再生が始まります)

 回転速度の単位はrad/sです。ジャイロスコープの値の意味は以下の通りです。

  • values[0]: X軸の回転速度
  • values[1]: Y軸の回転速度
  • values[2]: Z軸の回転速度

 このセンサーは姿勢の変化を検出するのに適しています。

 デモでは他のサンプルと同様、簡単のために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 4.4で追加されたセンサー

 今回はセンサーの中でも系統が似ていて、スマートフォンやウェアラブル端末で使用頻度が高そうな加速度センサー、重力センサー、ジャイロスコープを取り上げましたが、冒頭に記載した通り、Androidには多種多様なセンサーが存在します。

 次回は、Android 4.4で追加されたステップカウンターなどのセンサーを取り上げる予定ですので、お楽しみに。

「Androidで動く携帯Javaアプリ作成入門」バックナンバー
前のページへ 1|2|3       

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。