fresh digitable

めんどくさかったなってことを振り返ったり振り返らなかったりするための記録

SensorManager#registerListener()で値の取得間隔を設定できるらしいが…

この季節は部屋が大変暑くなるので私にもPCにもよろしくないです。ドヤリング的なことをしようにも今ひとつ踏み切れない感じです。去年、涼しい所で作業するためにアs、エイスースのウルトラブックを買ったので今年こそは活用したいです。


さて本題。

最近Androidのセンサまわりをprprしていて気づいたのですが、SensorManager#registerListener()ではAPI Level 9から値のおおよその取得間隔をマイクロ秒単位で指定できるそうです。
昔見ていた頃の記憶でSensorManager.SENSOR_DELAY_*キーワードのみの指定しかできなかったと思っていたのでやってみました。簡単なスニペットを貼ってみます。

SensorManager manager = (SensorManager)getSystemResource(SENSOR_MANAGER);
Sensor sensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// だいたい1秒間隔で加速度の値をlistenerで受け取る
manager.registerListener(listener, sensor, (int)1e6 /* micro sec. */);

ちなみに、SensorManager#getDefaultSensor()が返してくるsensorは、その端末がいくつか持つ同じセンサの値を、平均したりフィルタをかけたりして求めた値を返してくるそうです。

listenerを下記の感じで実装して、手持ちのIS12S(xperia acro hd、Android4.0.4)で実際の間隔を見てみました。

SensorEventListener listener = new SensorEventListener(){
   long post;
   public void onSensorChanged(SensorEvent event){
      long now = event.timestamp; // nano sec.
      Log.d(TAG, "sensor: " + event.sensor.getType() +
               ", interval: " + (now - post) / 1000 /* micro sec. */);
      post = now;
   }
   // 以下略
}

すると、、、

... interval: 70078
... interval: 72243
... interval: 71004
... interval: 108110
...

oh...
桁が足りない…しかもやたらと値がふらつく…一体何が起きているの…と思いセンサの種類をTYPE_GYROSCOPEとかに変えてみました。するとどうでしょう!大体1秒間隔で値が取れるではありませんか!それどころか端末が持ってるセンサは大概普通に1秒間隔で値を返してくる。

端末が持っているセンサ(加速度、重力、直線加速度、ジャイロ、近接、オリエンテーション)のうち、あかんかったのは加速度と近接だけでした。 このうち、近接センサは値が変わった時にだけ値を返すことになっている(Sensor#getMinDelay()が 0 を返す)ので、インターバルの設定が無視されるのは自然なことのような気がします。
面白いのは加速度センサがアカンのに重力、直線加速度センサはOKという事です。

SensorManager#getSensorList(Sensor.TYPE_ALL)でセンサ一覧を見ると、重力センサと直線加速度センサは2つずつ(ちゃんと調べてないのでわかりませんが、おそらくセンサのチップと、ソフト的に値を求めるやつ)持っているのに対して、加速度センサは1つだけ(おそらくセンサのチップ)でした。かといってチップしか持っていないようなセンサもインターバルの設定が効いているので、インターバルの設定が有効なのはソフトの実装とかハード側の仕様次第なのかなと予想しています。詳しいことは引き続き調べていきます。

今度書くときはログをちゃんととって載せよう。

続きを書きました。