デジモノ狂想曲!

デジタルデバイスの活用方法を模索しています。
最近iPhoneを買いました。いいですねあれ!!
なんで今まで買わなかったんだろう・・・

.

2009年06月20日

Androidを使って各種センサーの値を取得してみた


GDD Phone(HT-03A)に搭載されている各種センサをつかってアプリを作ろうと思い、ちょっとしたテストプログラムを作ってみました。

今回はサンプルに載っていない部分も作ってみました。
っということは、はじめてのandroidオリジナルプログラムかな?


というわけで、実験実験!!

 

焦らず急がず、順を追って考えていきましょう。

利用するセンサの種類

Android では、下記のようなセンサが搭載利用できるようです。
(もし、その機器に搭載されていれば・・・・)

  • 方位センサ
  • 加速度センサ
  • 温度センサ
  • 地場センサ
  • 光センサ
  • 近接センサ

今回は、そのうち方位センサ加速度センサを利用しました。
ついでに、GPSも同時に使ってみました。

どんな値が取得できるか

それぞれのセンサごとに取得出来る値のベクトルが異なります。

たとえば、加速度センサは、XYZの3軸で値を取ります。XY平面が液晶画面、そこから垂直方向がZ軸です。
方位センサも3軸の出力が得られます。それぞれ、方位、ロール、ピッチです。

どんな風に表示するか

テストのためのプログラムなので、あまり凝った表示にはしませんでした。
ただ単に、センサから取り出した値を表示するだけにしました。

たとえば、こんな感じで・・・

ORIENTATION_X: xxxxxx
ORIENTATION_Y: xxxxxx
ORIENTATION_Z: xxxxxx

ACCELERATION_X: xxxxxx
ACCELERATION_Y: xxxxxx
ACCELERATION_Z: xxxxxx

LATITUDE: xxxxxx
LONGITUDE: xxxxx

DATE_TIME: YYYY/MM/DD hh:mm:ss'xxxx

さて、ここでちょっとした問題があるみたいです。
今回使うAPIは1.1なのですが、それだとランドスケープが変化したときに、各センサの出力軸が変化するようです。
このため、本来はランドスケープによって軸を切り替えないといけないらしいです。
ちなみに、APバージョン1.5だとランドスケープで切り替わらないそうです。

コードの概略

いつもの参考書 によると、センサ値取得の手順は下記です

  • 利用できるセンサを調査する
  • センサのリスナを登録する
    • リスナは、センサの値が変化したときに実行される
  • リスナ中で、センサ値を解釈する

今回のコードは、詳しいサンプルが載っていませんでしたので、作るのにちょっと苦労しました。
まあ、そこをイロイロと考えるのが楽しいのですが・・・
コードの一部をこの記事末尾に乗っけておきますね。(キタナイコードで申し訳ないんですが・・・)

ちなみに、APIのバージョンは1.1です。


実行結果

しっかりとセンサの値が表示されています。
端末を動かすと、加速度(Accelaration)や方位(Orientation)が変化します。


20090620_sensorvalue01.png

動かしてみました。(端末を立ててみました。)

20090620_sensorvalue02.png

センサの値が更新される度に、画面がが更新されるようになっています。
いくつかのセンサがあるので、画面の更新が不定期なようです。

センサ出力値の解釈

加速度センサの値をみてみます。
机の上に置いたところで、重力加速度に近い値がでています。
1枚目のスクリーンショットではY軸、2枚目ではX軸です。
1枚目のスクリーンショットの値は、重力加速度とはちょっとずれています。
おそらく、机が水平でないために他の軸に分散しているのだと思われます。

方角センサの値はというと、
端末を上下に回転させてみると、X軸とY軸の値が変化します。 どちらも端末の傾きや回転角度を表しているようです。 机の上に置いて回転させてみると、Z軸が変化します。

というわけで、センサの出力値はそのままで計算に利用できそうです。

まとめ

今回のまとめです。

  • GDD Phone(HT-03A)には、方角センサと加速度センサが搭載されている。
  • これらのセンサ出力値は、値が変化するごとにリスナ関数より取得可能。
  • これらのセンサ出力値は、そのまま計算に利用可能である。

ソースコード

今回書いたソースコードです。
には載ってないので、参考のために書き残しておきます。
よろしければ参考にして下さい。(読みにくいコードで申し訳ないです・・・)

※APIのバージョンは1.1です。

package jp.hews.getsensorvalues;
import com.google.android.maps.GeoPoint;
import android.app.Activity;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.hardware.SensorManager; //SensorManagerを使うのに必要
import android.hardware.SensorListener; //SensorListenerを使うのに必要
import android.content.Context;
import android.view.View;
import android.widget.TextView;
import android.widget.Button;
import java.util.Calendar;
//import jp.hew.helloandroid.R;
public class GetSensorValues extends Activity 
 implements LocationListener{
 float SensorValue_Orientation_X;  //方位センサのX軸
 float SensorValue_Orientation_Y;  //方位センサのY軸
 float SensorValue_Orientation_Z;  //方位センサのZ軸
 int  SensorAccuracy_Orientation;  //方位センサの正確度
 
 float SensorValue_Accelerometer_X; //加速度センサのX軸
 float SensorValue_Accelerometer_Y; //加速度センサのY軸
 float SensorValue_Accelerometer_Z; //加速度センサのZ軸
 int  SensorAccuracy_Accelerometer; //方位センサの正確度
 double GPS_Latitude;     //GPSの緯度
 double GPS_Longitude;     //GPSの経度
 
 TextView mDisplayText;
 Button  mFinishButton;
 //位置情報を取得するためのマネージャ
 LocationManager mLocationManager;
 //位置情報の初期値
 static final long MIN_TIME = 0; // 通知の最小時間 [ms]
 static final float MIN_DISTANCE = 0; //通知の最短距離 [m]
 
 //表示する文字列を更新する。
 private void UpdateDisplayStrings(){
  StringBuffer buff = new StringBuffer();
  Calendar calendar = Calendar.getInstance();
  int year = calendar.get(Calendar.YEAR);
  int month = calendar.get(Calendar.MONTH);
  int day = calendar.get(Calendar.DAY_OF_MONTH);
  int hour = calendar.get(Calendar.HOUR_OF_DAY);
  int minute = calendar.get(Calendar.MINUTE);
  int second = calendar.get(Calendar.SECOND);
  int ms = calendar.get(Calendar.MILLISECOND);
  buff.append("ORIENTATION_ACCURACY: ");
  buff.append(SensorAccuracy_Orientation);
  buff.append("\n");
  buff.append("ORIENTATION_X: ");
  buff.append(SensorValue_Orientation_X);
  buff.append("\n");
  
  buff.append("ORIENTATION_Y: ");
  buff.append(SensorValue_Orientation_Y);
  buff.append("\n");
  
  buff.append("ORIENTATION_Z: ");
  buff.append(SensorValue_Orientation_Z);
  buff.append("\n");
  buff.append("\n");
  
  
  
  buff.append("ACCELERATION_ACCURACY: ");
  buff.append(SensorAccuracy_Accelerometer);
  buff.append("\n");
  buff.append("ACCELERATION_X: ");
  buff.append(SensorValue_Accelerometer_X);
  buff.append("\n");
  
  buff.append("ACCELERATION_Y: ");
  buff.append(SensorValue_Accelerometer_Y);
  buff.append("\n");
  
  buff.append("ACCELERATION_Z: ");
  buff.append(SensorValue_Accelerometer_Z);
  buff.append("\n");
  buff.append("\n");
  
  buff.append("LATITUDE : ");
  buff.append(GPS_Latitude);
  buff.append("\n");
  buff.append("LONGITUDE: ");
  buff.append(GPS_Longitude);
  buff.append("\n");
  buff.append("\n");
  
  buff.append("DATE_TIME: ");
  buff.append(year);
  buff.append("/");
  buff.append(month);
  buff.append("/");
  buff.append(day);
  buff.append(" ");
  buff.append(hour);
  buff.append(":");
  buff.append(minute);
  buff.append(":");
  buff.append(second);
  buff.append("'");
  buff.append(ms);
  
  mDisplayText.setText(buff);
  
 }
    public void onClick(View v)
    {
     if(v.getId() == R.id.finish_button){
      finish();
     }
    }
   
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        SensorManager sm = (SensorManager)getSystemService( SENSOR_SERVICE );
       
        int sensors = sm.getSensors();
       
        if ((sensors & SensorManager.SENSOR_ORIENTATION)!=0){
         //リスナの登録というか、有効化?
         sm.registerListener( mSensorListener,
              SensorManager.SENSOR_ORIENTATION |
              SensorManager.SENSOR_ACCELEROMETER);
        }
        SensorValue_Orientation_X = 0;
        SensorValue_Orientation_Y = 0;
        SensorValue_Orientation_Z = 0;
       
        SensorValue_Accelerometer_X = 0;
        SensorValue_Accelerometer_Y = 0;
        SensorValue_Accelerometer_Z = 0;
       
        GPS_Latitude = 0;
        GPS_Longitude = 0;
       
        //結果出力用のテキストボックス
        mDisplayText = (TextView)findViewById(R.id.text_view);
       
        //終了用のボタンの定義
        mFinishButton = (Button)findViewById(R.id.finish_button);
        mFinishButton.setOnClickListener(
          new View.OnClickListener(){
           public void onClick(View v){
            //クリックしたら終了
            finish();
           }
          }
        );
        //位置情報取得用のクラス
        mLocationManager = (LocationManager)getSystemService( Context.LOCATION_SERVICE);
    }
   
    public void onLocationChanged(Location location){
     //現在のGPS情報を取得
     GPS_Latitude = location.getLatitude();
     GPS_Longitude = location.getLongitude();
     UpdateDisplayStrings();
    }
   
    public void onProviderDisabled(String provider){
      //プロバイダが使用不能になった  
    }
   
    public void onProviderEnabled(String provider){
     //プロバイダが利用可能になった
    }
   
    public void onStatusChanged(String provider, int status, Bundle extras){
     //プロバイダの状態が変化した。
    }
    @Override
    protected void onResume(){
     super.onResume();
     //最後に取得した位置があれば表示する
     Location loc = mLocationManager.getLastKnownLocation(
       LocationManager.GPS_PROVIDER   );
     
     if(loc != null){
      onLocationChanged(loc);
     }
     
     //現在位置が変化したらメゾッドが呼び出されるよう登録する
     mLocationManager.requestLocationUpdates(
       LocationManager.GPS_PROVIDER,
       MIN_TIME,
       MIN_DISTANCE,
       this);
    }   
   
    SensorListener mSensorListener = new SensorListener(){
  public void onSensorChanged(int sensor, float[] values){
      switch(sensor){
   case SensorManager.SENSOR_ORIENTATION:
     //方位センサの値が変化した
     //ポートレイトかランドスケープかはとりあえず気にせずに
     SensorValue_Orientation_Z = values[0];
     SensorValue_Orientation_X = values[1];
     SensorValue_Orientation_Y = values[2];
    break;
    
   case SensorManager.SENSOR_ACCELEROMETER:
     SensorValue_Accelerometer_Z = values[0];
           SensorValue_Accelerometer_X = values[1];
           SensorValue_Accelerometer_Y = values[2];
    break;
   
   default:
    
    break;
   }
   //表示するテキストを生成する。
      UpdateDisplayStrings();
  }
  public void onAccuracyChanged(int sensor, int accuracy){
   if((sensor == SensorManager.SENSOR_ORIENTATION)){
    SensorAccuracy_Orientation = accuracy;
   }
      UpdateDisplayStrings();
  }
 };
}
 

以上






投稿: はせこう。 at 22:28 | Comment(0) | TrackBack(0) | Android
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/29944840

この記事へのトラックバック

ランキング投票!

RSS取得