Введение
Привет хабрасообщетво! Давно хотел написать статью, как однажды пришлось поработать с данными, получаемыми от датчиков HTC Desire, находящегося под управлением Android.
Целью было: определение перемещения объекта. То есть по данным с датчиков была возможность получить значения ускорений и моментов времени этих измерений. Далее обрабатывая данные уже вычислить скорость, и затем перемещение.
Работа с данными
Для начала пришлось повозиться со средой разработки для андроида. Ранее я не имел опыта программирования в середе Eclipse на Java, пришлось изучать основы. Но в итоге было написано приложение, которое собирало данные в базу SQLite на microSD карту. Вот первые данные, которые удалось получить:
Это график зависимости ускорения (ось У) от времени (ось X), в данном опыте телефон просто толкнули по столу чтобы он проскользил. Далее пошли уже всякие испытания, хотелось проверить например значение насыщения датчиков (максимально измеримое значение ускорения). Телефон двигался по круговой траектории с постепенным ускорением. График данных ниже:
Насыщение датчиков произошло на значении примерно 18,35 м/c^2.
Далее хотелось уже попробовать обработать получаемые данные:
Тут показан пример также скольжения телефона по столу: синяя линия — ускорение, красная – скорость и зеленая — перемещение. Этот не очень удачный, один из первых примеров. Тут перемещение так и не удалось определить.
Вот, более идеальный пример подобного опыта:
Здесь после обработки данных было получено правдоподобное значение перемещения телефона по столу.
В дальнейшем захотелось посмотреть, как будут выглядеть данные при ходьбе с телефоном:
А так же при беге с телефоном:
На примере ходьбы и бега уже четко видно как накапливаются различные ошибки с датчиков, для их дальнейшего исключения требуется подробное изучение процессов получения всех этих данных. В частности тут данные только с одной оси X, нет учета влияния на датчики ускорения силы тяжести (не учитывается вращение в пространстве телефона). Вот пример в котором это вращение, следовательно и влияние силы тяжести было исключено с одной из осей:
в данном опыте телефон лежал на столе, и одна из его сторон поднималась до привидения перпендикулярного положения телефона к столу. Здесь красная линя — угол (получаемый с компаса), зеленая — значение на датчике ускорения (по сути значение = ускорение + сила тяжести), фиолетовая — значение ускорения (с поправкой за значения угла). То есть в данном примере удалось исключить влияние силы тяжести.
Заключение
Данный вопрос очень интересен, и приведенные примеры всего лишь маленькое проявление моего любопытства. Как выяснилось, частота измерений с этих датчиков маловата для получения действительно качественных данных, но думаю, когда появится время все же заняться более подробным изучением этого вопроса.
UPD: откопал все таки исходный код одного из вариантов программы, прошу сильно не ругать это только знакомство с Java для android:
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.
Кому интересно тут проект приложения.