使用加速度计确定android的运动

时间:2017-04-06 16:20:32

标签: android

我用加速计传感器制作一个Android应用程序。我的目标是将智能手机向右移动,然后发送到服务器" RIGHT"当我将智能手机向左移动时,然后发送到服务器" LEFT"。为了实现这个功能,我知道我必须检测智能手机的移动。在实现此功能之前,我只想打印" RIGHT"或" LEFT"在textview,所以我搜索了一些代码,我写了这样的代码,

package com.example.administrator.motiondetector;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MotionDetector extends AppCompatActivity implements SensorEventListener {
    private TextView xText;
    private TextView yText;

    private SensorManager mSensorManager;
    private Sensor mSensorAccelerometer;

    private float xPastData;
    private float yPastData;
    private float zPastData;

    private float Speed;

    private float AccHistory[] = new float[3];

    private float AccelData[] = new float[3];

    String[] direction = {"NONE", "NONE"}

    private long lastTime;
    private static final int SHAKE_THRESHOLD = 800;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_motion_detector);
        xText = (TextView) findViewById(R.id.xText);
        yText = (TextView) findViewById(R.id.yText);

        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mSensorAccelerometer = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
        mSensorManager.registerListener(this, mSensorAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);
    }

    public void onSensorChanged (SensorEvent event) {
        if (event.sensor.getType() == mSensorAccelerometer.TYPE_ACCELEROMETER) {
            long currentTime = System.currentTimeMillis();
            long TimeInterval = currentTime - lastTime;
            if (TimeInterval > 100) {
                lastTime = currentTime;

                AccelData[0] = event.values[0];
                AccelData[1] = event.values[1];
                AccelData[2] = event.values[2];
                Speed = Math.abs(AccelData[0] + AccelData[1] + AccelData[2] - xPastData - yPastData - zPastData) / TimeInterval * 10000;

                if (Speed > SHAKE_THRESHOLD) {
                    Log.i("roosh", "Speed : " + Speed + ". Higher than Threshold");
                    float xChange = AccHistory[0] - AccelData[0];
                    float yChange = AccHistory[1] - AccelData[1];

                    AccHistory[0] = event.values[0];
                    AccHistory[1] = event.values[1];

                    if (xChange > 3) {
                        Log.i("roosh", "AccHistory[0] : " + AccHistory[0]);
                        Log.i("roosh", "AccelData[0] : " + AccelData[0]);
                        Log.i("roosh", "xChange : " + xChange + ". Direction is LEFT");
                        direction[0] = "LEFT";
                    } else if (xChange < -3) {
                        Log.i("roosh", "AccHistory[0] : " + AccHistory[0]);
                        Log.i("roosh", "AccelData[0] : " + AccelData[0]);
                        Log.i("roosh", "xChange : " + xChange + ". Direction is RIGHT");
                        direction[0] = "RIGHT";
                    }

                    if (yChange > 3) {
                        Log.i("roosh", "AccHistory[1] : " + AccHistory[1]);
                        Log.i("roosh", "AccelData[1] : " + AccelData[1]);
                        Log.i("roosh", "xChange : " + xChange + ". Direction is DOWN");
                        direction[1] = "DOWN";
                    } else if (yChange < -3) {
                        Log.i("roosh", "AccHistory[1] : " + AccHistory[1]);
                        Log.i("roosh", "AccelData[1] : " + AccelData[1]);
                        Log.i("roosh", "xChange : " + xChange + ". Direction is UP");
                        direction[1] = "UP";
                    }

                    xText.setText("X : " + direction[0]);
                    yText.setText("Y : " + direction[1]);
                }
                Log.i("roosh", "Speed : " + Speed + ". Lower than Threshold");

                xPastData = event.values[0];
                yPastData = event.values[1];
                zPastData = event.values[2];
            }
        }
    }

    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Not in use
    }
}

问题是这个。此代码有时效果很好。但有时会出现很多问题。这意味着textview显示我&#34; RIGHT&#34;虽然我从右到左移动了智能手机(textview必须显示我&#34; LEFT&#34;),textview显示我&#34; LEFT&#34;虽然我从左到右移动了智能手机(textview muse给我看了#34; RIGHT&#34;)。

我在stackoverflow中找到了一些解决方案,但是我失败了.. 有些人说我不仅要使用加速计传感器,还要使用更多的传感器,如陀螺仪或磁力计。但我无法理解如何修复这些传感器(加速度计,陀螺仪,磁力计)来检测智能手机的运动。

我认为代码在&#34; https://www.codeproject.com/Articles/729759/Android-Sensor-Fusion-Tutorial&#34;可以帮助我,但我无法理解这些代码...

所以,问题是这个。 我的代码有什么问题?我的密码有什么解决方案吗?或者是否有任何示例代码?或者有人可以告诉我如何理解&#34; https://www.codeproject.com/Articles/729759/Android-Sensor-Fusion-Tutorial&#34;的代码?

有些人会说&#34;请在stackoverflow&#34;但我已经做了.. 我真的想制作这个节目..

感谢您阅读

2 个答案:

答案 0 :(得分:0)

您是否阅读过Android开发者文档?

您可能感兴趣的几点:

来自Motion Sensors

  

加速度计使用标准传感器坐标系。实际上,这意味着当设备以自然方向平放在桌子上时,以下条件适用:

     
    
        
  1. 如果您将设备推向左侧(使其向右移动),则x加速度值为正。

  2.     
  3. 如果您将设备推到底部(因此它远离您),则y加速度值为正。

  4.     
  5. 如果以A m / s2的加速度将设备推向天空,则z加速度值等于A + 9.81,这对应于设备的加速度(+ A m / s2)减去重力(-9.81 m / s2)。

  6.     
  7. 固定装置的加速度值为+9.81,对应于装置的加速度(0 m / s2减去重力,即-9.81 m / s2)。

  8.        

在哪种情况下你的申请有效?

您也可以查看有关传感器坐标系的this information too

答案 1 :(得分:0)

There is no good way to detect the absolute movement of your phone using an accelerometer, it only detects relative movement / shaking.

You can start moving your phone to the right slowly, then stop it abruptly, you will see a spike in your accelerometer readings.

But if you start moving your phone to the left rapidly, then slowly stop it, you will see an identical spike in accelerometer reading, in the same direction.

You can imagine an accelerometer as a small ball floating freely inside your phone. When you move your phone to the right, the ball hits the left side, and the phone detects movement. When you move your phone to the left, then stop it, the ball hits the same left side, and detects the same movement, the phone has no way of knowing that you have started to move it earlier.

And since an accelerometer is not a very precise sensor, it cannot detect slow movement at all, unless you are using Project Tango device.

The only reliable reading an accelerometer can give you is the direction to the center of the Earth, thanks to gravity.

Gyroscope is usually much more precise sensor, but it only detects relative rotation, not linear movement. It also has no way to of knowing if you started to rotate your phone earlier, but you can combine it with accelerometer, which gives you an absolute direction to the center of the Earth, and with compass, which gives you the direction to the magnetic North pole, although from my experience, the compass drifts wildly even on high-end phones.

To do that same thing for accelerometer, you have to combine it with GPS, and GPS is too imprecise for that.