Gyroscopeを使った回転量の計算|Android開発
AndroidのセンサGyroscopeを使用して回転量を取る方法です。
解説
Gyroscope
からは各軸を中心とした角速度(rad/sec)が通知されます。
角速度は前回通知~今回通知までの値なので、通知時間を掛けてやると前回通知から今回通知までに移動した角度(rad)が算出されます。
角速度(rad/sec) × 時間(sec) = 角度(rad)
軸は下の図のようになっています。
使用例
下記サンプルでは、start時を0
(360
)とし、通知毎に移動角度を加算していくことで、時計回りなら360
~0
へ、反時計回りなら0
~360
へと値が変化します。
※移動量なので、続けるとマイナス値(負数)にもなるし、360
を超えます。
public class GyroscopeTest implements SensorEventListener {
private static final float NS2S = 1.0f / 1000000000.0f;
private float mLastTimestamp;
private float mRadianLandscape;
private float mRadianPortrait;
protected int mCurrentDegreeLandscape;
protected int mCurrentDegreePortrait;
protected int mDirection;
protected boolean isLandscape;
public static final Object SynchronizedObject = new Object();
public void start(int rotation, int direction) {
isLandscape = (rotation == 0 || rotation == 180);
synchronized (SynchronizedObject) {
mLastTimestamp = 0;
mRadianLandscape = 0;
mRadianPortrait = 0;
mDirection = direction;
}
}
protected int currentDegree() {
return isLandscape ? mCurrentDegreeLandscape : mCurrentDegreePortrait;
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_GYROSCOPE) {
return;
}
synchronized (SynchronizedObject) {
if (mLastTimestamp != 0) {
final float dT = (event.timestamp - mLastTimestamp) * NS2S;
float axisX = event.values[0];
float axisY = event.values[1];
float axisZ = event.values[2];
mRadianLandscape += (axisX * dT);
mRadianPortrait += (axisY * dT);
}
mLastTimestamp = event.timestamp;
int degreeLandscape = radianToDegree(mRadianLandscape);
int degreePortrait = radianToDegree(mRadianPortrait);
if (degreeLandscape < 0) {
degreeLandscape += 360;
}
if (degreePortrait < 0) {
degreePortrait += 360;
}
mCurrentDegreeLandscape = degreeLandscape;
mCurrentDegreePortrait = degreePortrait;
//Log.v("GyroscopeTest", String.format("Gyroscope: %d %d", mCurrentDegreeLandscape, mCurrentDegreePortrait));
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// NOP
}
protected static int radianToDegree(float radian) {
return (int) Math.floor(Math.toDegrees(radian));
}
}