Pull to refresh

Данные с датчиков HTC Desire

Reading time7 min
Views7.7K

Введение


Привет хабрасообщетво! Давно хотел написать статью, как однажды пришлось поработать с данными, получаемыми от датчиков HTC Desire, находящегося под управлением Android.
image
Целью было: определение перемещения объекта. То есть по данным с датчиков была возможность получить значения ускорений и моментов времени этих измерений. Далее обрабатывая данные уже вычислить скорость, и затем перемещение.

Работа с данными


Для начала пришлось повозиться со средой разработки для андроида. Ранее я не имел опыта программирования в середе 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.


Кому интересно тут проект приложения.
Tags:
Hubs:
Total votes 80: ↑69 and ↓11+58
Comments33

Articles