It's possible to compute distance and speed using only accelerometer, but with three conditions:
1. Linear movement - trajectory must be straight.
2. Slope of the road must be constant.
3. You must perform calibration procedure before start.
Where can you use this method with such restrictions - it's up to you... Now, how to do it:
1. We need something, implementing SensorEventListener interface. For the future use, let's add following abstract class:
public abstract class Accelerometer implements SensorEventListener {
protected float lastX;
protected float lastY;
protected float lastZ;
public abstract Point getPoint();
public void onAccuracyChanged(Sensor arg0, int arg1) {
}
}
and this will be our SensorEventListener:
public class XYZAccelerometer extends Accelerometer {
private static final int BUFFER_SIZE = 500;
// calibration
private float dX = 0;
private float dY = 0;
private float dZ = 0;
// buffer variables
private float X;
private float Y;
private float Z;
private int cnt = 0;
// returns last SenorEvent parameters
public Point getLastPoint(){
return new Point(lastX, lastY, lastZ, 1);
}
// returrns parameters, using buffer: average acceleration
// since last call of getPoint().
public Point getPoint(){
if (cnt == 0){
return new Point(lastX, lastY, lastZ, 1);
}
Point p = new Point(X, Y, Z, cnt);
reset();
return p;
}
// resets buffer
public void reset(){
cnt = 0;
X = 0;
Y = 0;
Z = 0;
}
public void onSensorChanged(SensorEvent se) {
float x = se.values[SensorManager.DATA_X] + dX;
float y = se.values[SensorManager.DATA_Y] + dY;
float z = se.values[SensorManager.DATA_Z] + dZ;
lastX = x;
lastY = y;
lastZ = z;
X+= x;
Y+= y;
Z+= z;
if (cnt < BUFFER_SIZE-1) {
cnt++;
} else
{
reset();
}
}
public int getCnt(){
return cnt;
}
public void setdX(float dX) {
this.dX = dX;
}
public void setdY(float dY) {
this.dY = dY;
}
public void setdZ(float dZ) {
this.dZ = dZ;
}
}
Calibrating accelerometer must be called before each experiment. Phone orientation must not be changed while measuring.
To calibrate accelerometer, i use this class:
public class Calibrator {
final static int UPDATE_INTERVAL = 400;
final static int ITERATIONS = 5;
Handler hRefresh;
XYZAccelerometer acc;
int eventNumber;
private LinkedList calData;
public Calibrator(Handler hRefresh, XYZAccelerometer acc, int eventNumber) {
this.hRefresh = hRefresh;
this.acc = acc;
this.eventNumber = eventNumber;
}
public void calibrate() {
final Timer calTimer = new Timer();
calData = new LinkedList();
acc.setdX(0);
acc.setdY(0);
acc.setdZ(0);
calTimer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
addCalData(calData);
if (calData.size() > ITERATIONS) {
calTimer.cancel();
try {
calSensor(calData);
} catch (Exception ex) {
try {
throw ex;
} catch (Exception ex1) {
hRefresh.sendEmptyMessage(5);
}
}
hRefresh.sendEmptyMessage(eventNumber);
}
}
},
0,
UPDATE_INTERVAL);
}
private void addCalData(LinkedList cD) {
Point p = acc.getPoint();
cD.add(p);
acc.reset();
}
private void calSensor(LinkedList cD) throws Exception {
if (cD.size() < ITERATIONS-1) {
throw new Exception("not enough data to calibrate");
}
float x = 0;
float y = 0;
float z = 0;
// Don't use first measure
for (int i = 1; i < cD.size(); ++i) {
x += cD.get(i).getX();
y += cD.get(i).getY();
z += cD.get(i).getZ();
}
x = x / (cD.size() - 1);
y = y / (cD.size() - 1);
z = z / (cD.size() - 1);
acc.setdX(-x);
acc.setdY(-y);
acc.setdZ(-z);
}
}
maintenance class to keep data of one measure
public class Point {
private float x = 0;
private float y = 0;
private float z = 0;
private int cnt = 1;
public float getX() {
return x/(float)cnt;
}
public float getY() {
return y/(float)cnt;
}
public float getZ() {
return z/(float)cnt;
}
public Point(float x, float y, float z, int cnt) {
this.x = x;
this.y = y;
this.z = z;
this.cnt = cnt;
}
public float getForce(){
return getX()*getX()+getY()*getY()+getZ()*getZ();
}
}
And class to process data of measure
public class MeasurePoint {
private float x;
private float y;
private float z;
private float speedBefore;
private float speedAfter;
private float distance;
private float acceleration;
private long interval;
private Point averagePoint;
public MeasurePoint(float x, float y, float z, float speedBefore, long interval, Point averagePoint) {
this.x = x;
this.y = y;
this.z = z;
this.speedBefore = speedBefore;
this.interval = interval;
this.averagePoint = averagePoint;
speedAfter = 0;
calc();
}
private void calc(){
//Acceleration as projection of current vector on average
acceleration = this.x*averagePoint.getX() +
this.y*averagePoint.getY() +
this.z*averagePoint.getZ();
acceleration = acceleration / ((float)Math.sqrt(averagePoint.getForce()));
float t = ((float)interval / 1000f);
speedAfter = speedBefore + acceleration * t;
distance = speedBefore*t + acceleration*t*t/2;
}
public String getStoreString(){
String s = "write here whatever you want";
return s;
}
// add getters
}
This one - to store and save data array
public class MeasureData {
// points from accelerometr
private LinkedList accData;
private LinkedList data;
// timer interval of generating points
private long interval;
public MeasureData(long interval) {
this.interval = interval;
accData = new LinkedList ();
data = new LinkedList ();
}
public void addPoint(Point p){
accData.add(p);
}
public void process(){
for(int i = 0; i < accData.size(); ++i){
Point p = accData.get(i);
float speed = 0;
if(i > 0){
speed = data.get(i-1).getSpeedAfter();
}
data.add(new MeasurePoint(p.getX(), p.getY(), p.getZ(), speed, interval, getAveragePoint()));
}
}
public boolean saveExt(Context con, String fname) throws Throwable {
try {
File file = new File(con.getExternalFilesDir(null), fname);
FileOutputStream os = new FileOutputStream(file);
OutputStreamWriter out = new OutputStreamWriter(os);
for (int i = 0; i < data.size(); ++i) {
MeasurePoint m = data.get(i);
out.write(m.getStoreString());
}
out.close();
} catch (Throwable t) {
throw (t);
}
return true;
}
private Point getAveragePoint() {
float x = 0;
float y = 0;
float z = 0;
for(int i = 0; i < accData.size(); ++i){
Point p = accData.get(i);
x += p.getX();
y += p.getY();
z += p.getZ();
}
return new Point(x, y, z, 1);
}
public float getLastSpeed(){
return data.getLast().getSpeedAfter();
}
public float getLastSpeedKm(){
float ms = getLastSpeed();
return ms*3.6f;
}
}
And, finally, how to use all this in your activity(I cleaned it up a lot, sorry if it will not complie - fill free to write it in comments:
public class TestActivity extends Activity {
static final int TIMER_DONE = 2;
static final int START = 3;
static final int CAL_TIMER_DONE = 4;
static final int ERROR = 5;
private StartCatcher mStartListener;
private XYZAccelerometer xyzAcc;
private SensorManager mSensorManager;
private static final long UPDATE_INTERVAL = 500;
private static final long MEASURE_TIMES = 20;
private Timer timer;
private TextView tv;
private Button testBtn;
int counter;
private MeasureData mdXYZ;
/** handler for async events*/
Handler hRefresh = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case TIMER_DONE:
onMeasureDone();
String es1 = Float.toString(Math.round(mdXYZ.getLastSpeedKm()*100)/100f);
tv.append(" END SPEED " + es1 + " " + es2 + " \n");
enableButtons();
break;
case START:
tv.append(" START");
timer = new Timer();
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
dumpSensor();
}
},
0,
UPDATE_INTERVAL);
break;
case ERROR:
Toast.makeText(getApplicationContext(), "ERROR", Toast.LENGTH_SHORT).show();
break;
}
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.txt);
testBtn = (Button) findViewById(R.id.btn);
}
@Override
protected void onResume() {
super.onResume();
tv.append("\n ..");
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
setAccelerometer();
setStartCatcher();
mSensorManager.registerListener(xyzAcc,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_GAME);
}
@Override
protected void onPause() {
mSensorManager.unregisterListener(xyzAcc);
super.onPause();
}
public void onButtonTest(View v) {
disableButtons();
mdXYZ = new MeasureData(UPDATE_INTERVAL);
counter = 0;
tv.setText("");
tv.append("Calibrating");
Calibrator cal = new Calibrator(hRefresh, xyzAcc, START);
cal.calibrate();
}
void dumpSensor() {
++counter;
mdXYZ.addPoint(xyzAcc.getPoint());
hRefresh.sendEmptyMessage(TICK);
if (counter > MEASURE_TIMES) {
timer.cancel();
hRefresh.sendEmptyMessage(TIMER_DONE);
}
}
private void enableButtons() {
testBtn.setEnabled(true);
}
private void setAccelerometer() {
xyzAcc = new XYZAccelerometer();
mSensorManager.registerListener(xyzAcc,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
}
private void disableButtons() {
testBtn.setEnabled(false);
}
private void onMeasureDone() {
try {
mdXYZ.process();
long now = System.currentTimeMillis();
mdXYZ.saveExt(this, Long.toString(now) + ".csv");
} catch (Throwable ex) {
Toast.makeText(this, ex.getMessage().toString(), Toast.LENGTH_SHORT);
}
}
}
<serviceLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<serviceButton
android:id="@+id/btn"
android:text="TEST"
android:layout_width="300px"
android:layout_height="200px"
android:onClick="onButtonTest" />
<serviceTextView
android:id = "@+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=":"
/>
<service/LinearLayout>
77 комментариев:
Hi Maep i had seen your post on stackoverflow(http://stackoverflow.com/questions/7858759/android-type-linear-acceleration-sensor-what-does-it-show) do you found the reason to use TYPE_LINEAR_ACCELERATION instead of TYPE_ACCELEROMETER ? Watching your code here seems not...I'm in your similar situation, i need the acceleration vector whitout gravity!!!! Thanx!
hi! no,TYPE_LINEAR_ACCELERATION still is wired thing i can't understand:)
hi can u place full project for finding speed and travelled distance .
please send me entire project to sravan0@yahoo.com
where is getSpeedAfter() method.
And StartCatcher Class.
please send my this poject to suno@ynet.sk
Getting problem for StartCatcher Class. So can you plz send me your project on sumant4943@gmail.com.
Please send me project to fox902008@gmail.com.
I can't find getSpeedAfter() method and StartCatcher Class.
Please help.
can you please send me your code to r.apurva14@gmail.com
hello! can I have the full project as well. Thank you.
Hello mate!
Could you please send me whole project ?
Thanks a lot!
accelgyro@gmail.com
Cheers!
Hi! Could you please send the source code of this project to me? Thanks.
bennychen0123@gmail.com
Hi there,great work! Can you please send me your full project @ aaditya.adi.91@gmail.com.
hey..could u please send me your project
at fayazy116@gmail.com
heyy,could you please send me your project at fayazy116@gmail.com
Can you please send full project to seenivasanv57@gmail.com?
Я так понял что ты из Росии ) Я твою статью на хабре еще видел.
Судя по твоему проекту с разгоном до 100, у тебя получилось это реализовать )
Я хочу сделать таксометр, и меня в принципе устраивает как он работает через GPS, но есть момент, что при остановке машины он бывает долго думает, и простой начинает считать по разному, то через 5 сек, то через 15.
Мне не важно правильно ли датчик будет определять скорость свыше 20 км/ч, но мне важно чтобы аксселерометр быстро реагировал на то, когда я остановился или сбросил скорость до значение меньше за 20 км в час.. Это реально сделать комбинируя данные с ГПС и датчика? Если да не мог ли бы ты помочь мне немного.. (Я твои сурцы пытался использовать, но после калибровки он мне выдает 20км/час скорость лежа на столе, что то там не то наверно, или руки кривые
Мне конечно эта тема интересна, но я сейчас не могу себе позволить что-то неделями учить, проекты горят, думать долго нельзя. Если не сложно напиши на e-mail shutter@inbox.com или напиши в скайп rumzik92, очень надеюсь на то, что поможешь... Заранее спасибо
Please send me entire project to sridhar.474@gmail.com
Hi Meap, would you please send me the entire project source code?
With Thanks and Regards,
Arshad
sorry I forgot to mention my email.
m99arshad@gmail.com
Wuth Thanks and Regards,
Arshad
Dear Maep,
This is my final year project, I got to be honest, mobile development is new to me (I'm mostly experienced with C programming on MCUs) but I want to learn and develop my skills in this field.
I want to develop a Vibration Analysis application. I want to use it to measure the vibration in an Elevator so one can analyze the riding comfort.
First, the phone will be put on the flooring in the middle of the cabin, the measurement should be along the Elevator's total travel (up to 1min ride) and at least following to 2 axis (X and Y, if I can measure following Z too, it will be great). Once those data are captured during this 1min, I want to plot them on a separate graphs (first graph: X position vs time, second graph: Y position vs time). Also, I might add the feature of measuring the elevator speed while traveling inside the cabin.
My questions are:
1- Should I use the acceleration or the Linear-acceleration sensor?
2- Can the accelerometer (on Samsung Note 2 for example) detect small vibrations? like ones that occurs in an elevator (around 15 m-g)
I want to know how hard can this project be, and if it's feasible or not. Can You send me the project to Anthony.A87@live.com so I can have a place to start with
Many Thanks
Hi! Can you send the entire project to badcipry92@yahoo.com ?
I'm having difficulties! Thanks!
Hi! Please, Can you send the entire project to eubeju@gmail.com ?
Thanks!
Could tou share the project on
Ahmed.salem@mufix.org
Hi there,great work! Can you please send me your full project
hadi.dehghani.t@gmail.com
Please send me project to weihao0220@gmail.com
Hi Meap, would you please send me the entire project source code to my email address lichienmine@gmail.com ?
With Thanks and Regards,
Lichien
Hi,
send me please entire project
Hoodrij@gmail.com
Hi,
can u send me code on star.ankit90@gmail.com
Thanks!
please send my this poject to
emily2.3kim@gmail.com
Hi. plz Send me this project to cbmoon8@naver.com
I really need your full code..!
thnx.
Can you please send me whole project on bodemarkovic@gmail.com
Thank you in advance! It is very nice project.
Can anyone send me whole project on filip100janovski@gmail.com
Hi there,great work! Can you please send me your full project to deepak.d.hosur@gmail.com
geeting problem: where is getSpeedAfter() method.
And StartCatcher Class.
Please send me full code to deepak.d.hosur@gmail.com
Hi! I have some problems.. Can you please send me whole project on a.mekhedenko@gmail.com
Thank you very much!
can I please have the project
tarazansafak@gmail.com
thanks!
Please send me the project:
znaglis@gmail.com
Thanks in advance
Can you send me your project?
My email: hoang.mirs@gmail.com
Thanks for such a nice tutorial, But I am not able to run this on my machine. Please send whole project to my mail address anujs1991@gmail.com and kindly upload your project to github and post its link so that most of user can take benefit and praise your work.
Thanks.
Hi,
In calibration what you are doing, can you please elaborate.
Thanks
Sudhakar
Desde colombia , envia correo rapiaven1890@gmail.com, gracias
Hey share the full source
plz plz plz.....plz send me the whole project on my email: agarwalsarthak22@gmail.com
i need it urgently. Thank you in advance. :)
URGENT ANYONE!!
Could you please send me to fgrass91@gmail.com I would be really thankful.
I couldn't get it to work.
I really would need that and it would help me a lot.
THANK YOU!!
could you please send source code project to prakash.cse1988@gmail.com
could you please send source code project to kskung12@gmail.com
kindly send the whole project on the given id.it will be very useful for
ahmad-arif121@hotmail.com
Hey share the StartCatcher java file to my mail id : snarendran89@gmail.com
hiiii can u please send me whole code on sharmagautam422@gmail.com
HI, could someone send me the Whole Project, I really need this startu understanding of all handles ALL.
Tks in advance
Marco Santos **** marrco.santos@gmail.com
Hi I'm having some difficulties. can u pls send the whole project to sanjaykrishna031@gmail.com.Thanks
Dear Sir,
Can you please share with me this project?
I researching about calculate distance while walking in android. Thank you for help!
Dear Sir,
Could you send me this project to danielwilson8654@gmail.com
Nice project. Please send the source simopatrick.simpat@gmail.com
Great work. Can you please send it to ozanadgzl.job@gmail.com
Awesome work. Can you please send me your code creedphilip.1994@gmail.com
Hi your Code is brilliant,
would you please send me the whole Project, too?
@ code@neusinger.de
Thanks a alot!
hi nice explination. can u please share code to svajjaramatti@gmail.com
thank u in advance
Hi, can you please send code to jesusmartinezdiaz8@gmail.com
thank you in advance
Hi,this extra ordinary.
help me forward that whole sourcecode to my email raymondkiyingi03@gmail.com.
Share the source code on siran10289@gmail.com
could you please share the complete code jahanzeb.naeem@hotmail.com
Hi, could you please send code to :
ahmedberriche1993@gmail.com
Thank you!!
Hi! Could you please send the source code of this project to me? Thanks
hiral.stegowl@gmail.com
Hi! Could you please send the source code of this project to me? Thanks
abrados.1@gmail.com
Можно ли получить исходный код проекта. Почта lana.chebotareva.95@mail.ru
Please send me project to lucascoelhosi96@gmail.com
пишет...
Please send me project to mohamed.bahaa.embaby@gmail.com
Отправить комментарий