Xamarin.Android 方位の取得2(磁気センサー/加速度センサー)
1 方位の取得方法
Androidで方位を取得する方法は、次の2つがあります。
(1) TYPE_ORIENTATION(傾きセンサー)による方法
(2) TYPE_MAGNETIC_FIELD(磁気センサー)とTYPE_ACCELEROMETER(加速度センサー)による方法
今回は、(2)の磁気センサーと加速度センサーを使用してみます。
なお、API Level8 で「方位角」及び「傾き」を求める場合は、TYPE_ORIENTATIONは非推奨になっているようです。
2 磁気センサー(TYPE_MAGNETIC_FIELD)及び加速度センサー(TYPE_ACCELEROMETER)
センサー自体の使用方法は、傾きセンサーの時と同じですが、「方位角」と「傾き」は、SensorManagerのメソッドで計算しています。http://developer.android.com/reference/android/hardware/SensorManager.html
// 加速度センサーと磁気センサーの値から回転行列を求める public static bool GetRotationMatrix(float[] R, float[] I, float[] gravity, float[] geomagnetic) // 端末の画面設定に合わせる変換行列を求める(以下は, 縦表示で画面を上にした場合) public static bool RemapCoordinateSystem(float[] inR, Android.Hardware.Axis X, Android.Hardware.Axis Y, float[] outR) // 方位角及び傾きを求める public static float[] GetOrientation(float[] R, float[] values)
サンプルは、傾きセンサーの値も合わせて表示して違いを比べて見ましたが、ほとんど同じでした。
※回転角の符号が逆転しているのに注意が必要です。
[Activity(Label = "AndroidApplication1", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity, ISensorEventListener{ private SensorManager _senseManager; private TextView _textView; protected override void OnCreate(Bundle bundle){ base.OnCreate(bundle); SetContentView(Resource.Layout.Main); _senseManager = (SensorManager) GetSystemService(SensorService); _textView = FindViewById<TextView>(Resource.Id.textView); } protected override void OnResume(){ base.OnResume(); //リスナー登録 _senseManager.RegisterListener(this, _senseManager.GetDefaultSensor(SensorType.MagneticField),SensorDelay.Ui); _senseManager.RegisterListener(this, _senseManager.GetDefaultSensor(SensorType.Accelerometer),SensorDelay.Ui); _senseManager.RegisterListener(this, _senseManager.GetDefaultSensor(SensorType.Orientation), SensorDelay.Ui); } protected override void OnPause(){ base.OnPause(); //リスナー解除 _senseManager.UnregisterListener(this); } //ISensorEventListenerで必須 public void OnAccuracyChanged(Sensor sensor, SensorStatus accuracy){ } float [] _aVal; float [] _mVal; float[] _oVal; public void OnSensorChanged(SensorEvent e) { //センサー値の取得 switch (e.Sensor.Type){ case SensorType.Accelerometer: //加速度センサー _aVal = new float[3]; _aVal = e.Values.ToArray(); break; case SensorType.MagneticField: //磁気センサー _mVal = new float[3]; _mVal = e.Values.ToArray(); break; case SensorType.Orientation: //傾きセンサー _oVal = new float[3]; _oVal = e.Values.ToArray(); break; } var sb = new System.Text.StringBuilder(); if (_oVal != null) { sb.Append(String.Format("傾きセンサー\n")); sb.Append(String.Format("方位角:{0:F1}\n", _oVal[0])); sb.Append(String.Format("傾斜角:{0:F1}\n", _oVal[1])); sb.Append(String.Format("回転角:{0:F1}\n", _oVal[2])); sb.Append(String.Format("\n")); } if (_aVal != null && _mVal != null) { var R1 = new float[16]; var R2= new float[16]; var I = new float[16]; var val = new float[3]; // 加速度センサーと磁気センサーの値から回転行列を求める SensorManager.GetRotationMatrix(R1, I, _aVal, _mVal); // 端末の画面設定に合わせる変換行列を求める(以下は, 縦表示で画面を上にした場合) SensorManager.RemapCoordinateSystem(R1, Axis.X, Axis.Y, R2); // 方位角及び傾きを求める SensorManager.GetOrientation(R2, val); //ラジアンを角度に変換 for (var i = 0; i < 3; i++) { val[i] = (float)(val[i] * 180 / Math.PI); } sb.Append(String.Format("磁気センサー + 加速度センサー\n")); sb.Append(String.Format("方位角:{0:F1}\n", (val[0] < 0) ? val[0] + 360 : val[0])); sb.Append(String.Format("傾斜角:{0:F1}\n", val[1])); sb.Append(String.Format("回転角:{0:F1}\n", val[2])); } //表示 _textView.Text = sb.ToString(); } }