はじめに
こんにちはhabrasobschestveto! 長い間、Androidを実行しているHTC Desireのセンサーから受信したデータをどのように処理しなければならないかという記事を書きたいと思いました。
目標は、オブジェクトの動きを判断することでした。 つまり、センサーからのデータによれば、これらの測定の加速度と時間の値を取得することができました。 データをさらに処理すると、すでに速度が計算されてから移動します。
データを操作する
まず、Androidの開発環境をいじる必要がありました。 以前、JavaのEclipseの途中でプログラミングの経験がなかったため、基本を学ぶ必要がありました。 しかし、最終的に、microSDカード上のSQLiteデータベースにデータを収集するアプリケーションが作成されました。 取得された最初のデータは次のとおりです。
これは、加速度(Y軸)対時間(X軸)のグラフです。この実験では、電話をテーブルの周りに押して滑らせました。 その後、すべての種類のテストが行われました。たとえば、センサーの飽和値(測定可能な最大加速度値)を確認したかったのです。 電話機は徐々に加速しながら円形の経路を移動しました。 以下のデータグラフ:
センサーの飽和は、約18.35 m / s ^ 2の値で発生しました。
次に、受信したデータを既に処理しようとした:
ここで、テーブルの周りで電話機をスライドさせる例を見ることができます。青い線は加速度、赤い線は速度、緑の線は動きです。 これは最初の例の1つで、あまり成功していません。 ここでは、変位は決定されませんでした。
そのような経験のより理想的な例を次に示します。
ここでは、データを処理した後、電話をテーブル上で移動するためのもっともらしい値が取得されました。
将来的には、携帯電話を持って歩いたときにデータがどのように見えるかを見たいと思いました。
また、電話で実行する場合:
ウォーキングとランニングの例では、センサーからのさまざまなエラーがどのように蓄積するかがすでにはっきりとわかります;さらに除外するには、これらすべてのデータを取得するプロセスの詳細な調査が必要です。 特に、1つのX軸からのデータのみがあり、重力加速度センサーへの影響は考慮されていません(電話空間の回転は考慮されていません)。 この回転、したがって重力の影響が軸の1つから除外された例を次に示します。
この実験では、携帯電話はテーブルの上にあり、その側面の1つは携帯電話のテーブルに対する垂直位置のゴーストまで上昇しました。 ここで、赤い線は角度(コンパスから取得)、緑は加速度センサーの値(実際には値=加速度+重力)、紫は加速度値(角度値に対して調整済み)です。 つまり、この例では、重力の影響を排除することができました。
おわりに
この質問は非常に興味深いものであり、与えられた例は私の好奇心のほんのわずかな現れです。 結局のところ、これらのセンサーからの測定の頻度は、本当に高品質のデータを取得するのに十分ではありませんが、この問題のより詳細な調査を行う時期になると思います。
UPD:プログラムオプションの1つと同じソースコードを掘り下げました。AndroidのJavaに精通しているためだけに、あまりoldらないでください。
package com.dimond.acc;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.database.sqlite.SQLiteDatabase;
public class acc extends Activity implements SensorListener {
public class AXYZTdata
{
float ax;
float ay;
float az;
long time;
public AXYZTdata( float in_ax, float in_ay, float in_az, long in_time)
{
ax = in_ax;
ay = in_ay;
az = in_az;
time = in_time;
}
}
SensorManager sm = null ;
final String tag = "logging" ;
private EditText MassivN;
TextView DataText;
String TimeNowtmp;
int N, sec, stroka=0;
AXYZTdata[] mass = new AXYZTdata[10000];
float acc_x, acc_y, acc_z, acc_time = 0;
SQLiteDatabase mDatabase = SQLiteDatabase.openOrCreateDatabase( "/mnt/sdcard/DB/" +String.valueOf(System.currentTimeMillis())+ ".db" , null );
int onoff=0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
sm = (SensorManager) getSystemService(SENSOR_SERVICE);
Button start = (Button) findViewById(R.id.Start);
Button stop = (Button) findViewById(R.id.Stop);
Button write = (Button) findViewById(R.id.Write);
DataText = (TextView) findViewById(R.id.data);
//
String DATABASE_CREATE =
"create table accdb" +
"(_id integer primary key autoincrement, " +
"acc_x text not null," +
"acc_y text not null," +
"acc_z text not null," +
"time_h_m_s text not null);" ;
mDatabase.execSQL(DATABASE_CREATE);
//
start.setOnClickListener( new OnClickListener() {
public void onClick(View arg0)
{
startwrite();
}
});
//
stop.setOnClickListener( new OnClickListener() {
public void onClick(View arg0)
{
stopwrite();
}
});
//
write.setOnClickListener( new OnClickListener() {
public void onClick(View arg0)
{
masstosql();
DataText.setText( "Writed!!!" );
}
});
}
public void startwrite()
{
onoff=1;
return ;
}
public void stopwrite()
{
onoff=0;
DataText.setText(String.valueOf(stroka));
return ;
}
public void masstosql()
{
long StartTime = mass[0].time;
for ( int i=0; i<stroka; i++)
{
mDatabase.execSQL(String.format( "INSERT INTO accdb (acc_x, acc_y, acc_z, time_h_m_s) VALUES ('%s','%s','%s','%s');" ,
mass[i].ax, mass[i].ay, mass[i].az, mass[i].time-StartTime));
}
return ;
}
public void onSensorChanged( int sensor, float [] values) {
synchronized ( this ) {
Log.d(tag, "onSensorChanged: " + sensor + ", x: " + values[0] + ", y: " + values[1] + ", z: " + values[2]);
if (sensor == SensorManager.SENSOR_ACCELEROMETER && onoff==1) {
AXYZTdata tmp;
tmp = new AXYZTdata(values[0], values[1],values[2], System.currentTimeMillis());
mass[stroka] = tmp;
stroka++;
}
}
}
public void onAccuracyChanged( int sensor, int accuracy) {
Log.d(tag, "onAccuracyChanged: " + sensor + ", accuracy: " + accuracy);
}
@Override
protected void onResume() {
super.onResume();
sm.registerListener( this , SensorManager.SENSOR_ACCELEROMETER, SensorManager.SENSOR_DELAY_FASTEST);
}
@Override
protected void onStop() {
sm.unregisterListener( this );
super.onStop();
}
}
* This source code was highlighted with Source Code Highlighter .
ここで誰がアプリケーションプロジェクトを気にしますか。