android - 如何在android中使用加速度计传感器计算运行速度

标签 android accelerometer

我尝试在 Android 中计算运行速度传感器 TYPE_LINEAR_ACCELEROMETER,但我得到的结果非常不准确。计算出的平均加速度始终为正值,因此不断增加。这是我的程序和代码,请告诉我什么是从 3 轴加速度计数据计算的正确方法以及我的代码哪里出错了。

我所做的是:

我正在获取 xyz 方向的加速度值

产生的加速度a1 = sqrt(x*x + y*y + z*z)

5 加速度读数的平均值:

Avg(4) = `(a0 + a1 + a2 + a3 + a4) / 5`

时间增量:

Tdelta = (time of Avg(4)) - (time of Avg(0))

最初 V(0)0 之后 V(0) 是之前计算的速度,因此:

V(1) = V(0) + at = 0 + Avg(1)
V(2) = V(1) + at = V(1) + Avg(2)
V(n) = V(n-1) + at = V(n-1) + Avg(n)

这就是我获取速度值的方式,但这不是正确的速度。请指导我。

这是代码:

public class TestCalculateVelocityActivity extends Activity implements OnClickListener, SensorEventListener {

    final String TAG = getClass().getName().toString();
    SensorManager mSensorManager;
    Sensor mAccelerometer;
    TableLayout accTable;
    TextView accl, spd, spd_kmph;
    Button btnStart, btnStop, btnClear;
    Timer updateTimer;
    float []linearAcceleration = new float[3];
    Velocity velocity;
    Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        initSensor();

        accTable =(TableLayout)findViewById(R.id.country_table);

        //accl = (TextView)findViewById(R.id.accl);
        spd = (TextView)findViewById(R.id.spd);
        spd_kmph = (TextView)findViewById(R.id.spd_kmph);

        btnStart = (Button)findViewById(R.id.buttonStart);
        btnStart.setOnClickListener(this);
        btnStop = (Button)findViewById(R.id.buttonStop);
        btnStop.setOnClickListener(this);
        btnClear= (Button)findViewById(R.id.buttonClear);
        btnClear.setOnClickListener(this);
    }

    private void initSensor() {
        mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
        if(mAccelerometer == null) {
            Toast.makeText(this, "Accelerometer sensor not available", Toast.LENGTH_SHORT).show();
            finish();
        }
    }

    void fillTable(float values[]) {

        float[] val = values;
        TableRow row;
        TextView t1, t2, t3;
        //Converting to dip unit
        int dip = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                (float) 1, getResources().getDisplayMetrics());

        //for (int current = 0; current < CountriesList.abbreviations.length; current++) {
        row = new TableRow(this);

        t1 = new TextView(this);
        t1.setTextColor(Color.WHITE);
        t1.setBackgroundColor(Color.GRAY);
        t2 = new TextView(this);
        t2.setTextColor(Color.WHITE);
        t2.setBackgroundColor(Color.LTGRAY);
        t3 = new TextView(this);
        t3.setTextColor(Color.WHITE);
        t3.setBackgroundColor(Color.GRAY);

        t1.setText(""+val[0]);
        t2.setText(""+val[1]);
        t3.setText(""+val[2]);

        t1.setTypeface(null, 1);
        t2.setTypeface(null, 1);
        t3.setTypeface(null, 1);

        t1.setTextSize(15);
        t2.setTextSize(15);
        t3.setTextSize(15);

        t1.setWidth(150 * dip);
        t2.setWidth(150 * dip);
        t3.setWidth(150 * dip);
        t1.setPadding(20*dip, 0, 0, 0);
        row.addView(t1);
        row.addView(t2);
        row.addView(t3);

        accTable.addView(row, new TableLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    }

    public void onClick(View v) {

        if(v == btnStart) {
            mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
            velocity = new Velocity();
            updateTimer = new Timer("velocityUpdate");
            handler = new Handler();
            updateTimer.scheduleAtFixedRate(new TimerTask() {
                public void run() {
                    calculateAndUpdate();
                }
            }, 0, 1200);
        }else  if(v == btnStop) {
            mSensorManager.unregisterListener(this);

            displayVelocityValues();
            displayVelocityTable();
            velocity = null;
            handler = null;
            updateTimer.cancel();


        } else if(v == btnClear) {
            accTable.removeAllViews();
        }
    }

    private void displayVelocityTable() {
        try {
            accTable.removeAllViews();
            double[] vl = velocity.getVlArray();
            for(int i = 0; i<vl.length; i++) {
                /*Log.d(TAG, "v = " + vl[i] + "mps, "+(vl[i] * 3.6)+ " kmph");*/


                //float[] val = values;
                TableRow row;
                TextView t1, t2;
                //Converting to dip unit
                int dip = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        (float) 1, getResources().getDisplayMetrics());

                //for (int current = 0; current < CountriesList.abbreviations.length; current++) {
                row = new TableRow(this);

                t1 = new TextView(this);
                t1.setTextColor(Color.WHITE);
                t1.setBackgroundColor(Color.GRAY);
                t2 = new TextView(this);
                t2.setTextColor(Color.WHITE);
                t2.setBackgroundColor(Color.LTGRAY);


                t1.setText(""+vl[i]);
                t2.setText(""+(vl[i] * 3.6));


                t1.setTypeface(null, 1);
                t2.setTypeface(null, 1);


                t1.setTextSize(15);
                t2.setTextSize(15);

                t1.setWidth(200 * dip);
                t2.setWidth(200 * dip);

                t1.setPadding(20*dip, 0, 0, 0);
                row.addView(t1);
                row.addView(t2);


                accTable.addView(row, new TableLayout.LayoutParams(
                        LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
            }
        } catch(NullPointerException e) {
            e.printStackTrace();
        }
    }

    public void displayVelocityValues() {
        try {
            double[] vl = velocity.getVlArray();
            for(int i = 0; i<vl.length; i++) { 
                Log.d(TAG, "v = " + vl[i] + "mps, "+(vl[i] * 3.6)+ " kmph");
            }
        } catch(NullPointerException e) {
            e.printStackTrace();
        }
    }

    private void calculateAndUpdate() {

        final double vel = velocity.getVelocity(linearAcceleration, System.currentTimeMillis());
        final double velKmph = vel * 3.6;
        //spd.setText("v = "+ velKmph + " kmph");

        handler.post(new Runnable() {
            public void run() {

                //Log.d(getClass().getName().toString(), "Setting velocity = " + velKmph+ " kmph");
                spd.setText("v = "+ vel + " mps");
                spd_kmph.setText("v = "+ velKmph + " kmph");
            }
        });
    }



    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        linearAcceleration[0] = event.values[0];
        linearAcceleration[1] = event.values[1];
        linearAcceleration[2] = event.values[2];        

        fillTable(linearAcceleration);
    }
}



public class Velocity {

    private final String TAG = getClass().getName().toString();
    int sampleCounter = 0;
    final int totalSamples = 5;
    long time0, nAccel;
    static int i=0; 
    double aDelT0 = 0, v0 = 0, v = 0;

    final int totalVelocityValues = 1000;
    double []velocityValues = new double[totalVelocityValues];

    //float []linearAcceleration = new float[3];

    //final int totalAccl = 5;
    double []accel = new double[totalSamples];

    private double getAvg(double[] a) {
        double total = 0;
        for(int i = 0; i<a.length; i++) 
            total = total + a[i];
        return (total / a.length);
    }

    private double getAcceleration(float[] linearAcceleration) {
        return Math.sqrt(Math.pow(linearAcceleration[0], 2) + Math.pow(linearAcceleration[0], 2) + Math.pow(linearAcceleration[0], 2));
    }

    public double getVelocity(float[] linearAcceleration, long time1) {

        //this.linearAcceleration = linearAcceleration;

        try {
            if(sampleCounter < (totalSamples-1)) {
                if(sampleCounter == 0) 
                    time0 = time1;
                accel[sampleCounter] = getAcceleration(linearAcceleration);     
                sampleCounter++;    
            } else if(sampleCounter == (totalSamples-1)) {
                accel[sampleCounter] = getAcceleration(linearAcceleration);

                double avgAccel = getAvg(accel);
                long timeDelta = ((time1 - time0) / 1000);
                double aDelT1 = (avgAccel * timeDelta);
                Log.d(TAG, "aDelT1 = "+avgAccel +" * "+timeDelta + " = "+aDelT1 );

                v = calculateVelovity(aDelT1);
                if(i !=totalVelocityValues) {
                    velocityValues[i]=v;
                    i++;
                } else {
                    for(int j=0;j<(totalVelocityValues-1);j++)
                        velocityValues[j]=velocityValues[j+1];
                    velocityValues[totalVelocityValues -1]=v;
                }
                sampleCounter = 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return v;
    }

    private double calculateVelovity(double aDelT1) {
        double v = v0 + (aDelT1 - aDelT0);
        Log.d(TAG, "v = "+v0+ "+ ("+aDelT1+" - "+aDelT0+") = "+v);
        v0 = v;
        aDelT0 = aDelT1;
        return v;
    }



    public double[] getVlArray() {
        return velocityValues;
    }

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<LinearLayout 
    android:layout_width="fill_parent"
     android:layout_height="wrap_content"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/spd"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="5dip"
        android:layout_weight="1"
        android:background="@android:color/darker_gray"
        android:gravity="center_vertical|center_horizontal"
        android:text="speed (kmph)"
        android:textColor="@android:color/white"
        android:textSize="20dip"
        android:textStyle="bold"
        android:typeface="sans" />

    <TextView
        android:id="@+id/spd_kmph"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="5dip"
        android:layout_weight="1"
        android:background="@android:color/darker_gray"
        android:gravity="center_vertical|center_horizontal"
        android:text="ooooo"
        android:textColor="@android:color/white"
        android:textSize="20dip"
        android:textStyle="bold"
        android:typeface="sans" />


    <TextView  
        android:text="Acceleration Data"
            android:textColor="@android:color/white"
            android:gravity="center_vertical|center_horizontal"
            android:textSize="20dip"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:layout_marginBottom="5dip"
            android:typeface="sans"
            android:layout_weight="1"
            android:background="@android:color/darker_gray"/>


</LinearLayout>

<LinearLayout android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <Button android:id="@+id/buttonStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_weight="1"
        android:text="Start" />

    <Button android:id="@+id/buttonClear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_weight="1"
        android:text="Clear" />

     <Button android:id="@+id/buttonStop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_weight="1"
        android:text="Stop" />

</LinearLayout>

<RelativeLayout android:id="@+id/rl_country_heading"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/darker_gray">

    <TextView android:id="@+id/tv_11"
        android:layout_width="70dip"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="X"
        android:textStyle="normal|bold"
        android:textColor="@android:color/white"
        android:textSize="18dip">
    </TextView>

    <TextView android:id="@+id/tv_12"
        android:layout_width="150dip"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Y"
        android:textStyle="normal|bold"
        android:textColor="@android:color/white"
        android:textSize="18dip"
        android:layout_toRightOf="@+id/tv_11">
    </TextView>

    <TextView android:id="@+id/tv_13"
        android:layout_width="150dip"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Z"
        android:textStyle="normal|bold"
        android:textColor="@android:color/white"
        android:textSize="18dip"
        android:layout_toRightOf="@+id/tv_12">
    </TextView>
</RelativeLayout>

<LinearLayout android:id="@+id/ll_country"
    android:layout_height="fill_parent"
     android:layout_width="fill_parent">

    <ScrollView android:id="@+id/ScrollView11"
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent"
        android:fillViewport="true">

        <LinearLayout android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dip">

            <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="fill_parent" 
                android:layout_height="fill_parent"
                android:stretchColumns="0,1"
                android:id="@+id/country_table"
                android:background="@android:color/black">
            </TableLayout>  
        </LinearLayout>
    </ScrollView>
</LinearLayout>

最佳答案

您使用 getAcceleration 计算出加速度的总大小并丢失所有方向信息,因此它始终为正数。

您需要考虑方向,并且随着手机的转动而变化,因此您必须使用陀螺仪。

即使您获得了正确的代码,但典型手机上传感器的准确性意味着您很快就会失去任何准确性。

如果你想跑得快,看看gps....

编辑。

忘了说你没有考虑重力。你必须消除重力的影响。

关于android - 如何在android中使用加速度计传感器计算运行速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13264718/

相关文章:

android - Android 上的 OpenGL 线段光栅化

java - ConcurrentModificationException - 无法启动 Activity

android - 电子邮件中的附件

android - 在一行中显示一个对象的多个值

android - 如何在没有gps的情况下检查android手机是否被移动

java - Android 加速度计是毫秒还是微秒?

android - 如何防止 LinearLayout Android 菜单中按钮之间的空格?

python - 加速度计数据写入文件,然后绘制 Matplotlib 图形(3 个子图 [x, y, z])

java - 安卓加速度计

iphone - 如何从 iphone 的 X、Y、Z 加速度计读数计算行进方向的加速度/减速度