Android 如何使用加速度计获得运动方向?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10476625/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I get the direction of movement using an accelerometer?
提问by Marcos Passos
I'm developing a Android application and I would like to know if is possible detect the direction of movement with one axis fixed. For example, I want put my phone on the table and detect the direction when I move it (left, right, up and down). The distance is not necessary, I just want know the accurate direction.
我正在开发一个 Android 应用程序,我想知道是否可以检测一个固定轴的运动方向。例如,我想将手机放在桌子上,并在移动时检测方向(向左、向右、向上和向下)。距离不是必需的,我只想知道准确的方向。
回答by Louth
Yes.
是的。
Using the SensorEventListener.onSensorChanged(SensorEvent event)
you can determine the values provided along the X & Y axis. You would need to record these values and then compare them to any new values that you receive on subsequent calls to the onSensorChanged
method to get a delta value. If the delta value on one axis is positive then the device is moving one way, if its negative its moving the opposite way.
使用SensorEventListener.onSensorChanged(SensorEvent event)
可以确定沿 X 和 Y 轴提供的值。您需要记录这些值,然后将它们与您在后续调用该onSensorChanged
方法时收到的任何新值进行比较以获取增量值。如果一个轴上的 delta 值为正,则设备向一侧移动,如果为负,则向相反方向移动。
You will probably need to fine tune both the rate at which you receive accelerometer events and the threshold at which you consider a delta value to indicate a change in direction.
您可能需要微调您接收加速度计事件的速率和您认为 delta 值以指示方向变化的阈值。
Here's a quick code example of what I'm talking about:
这是我正在谈论的快速代码示例:
public class AccelerometerExample extends Activity implements SensorEventListener {
TextView textView;
StringBuilder builder = new StringBuilder();
float [] history = new float[2];
String [] direction = {"NONE","NONE"};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = new TextView(this);
setContentView(textView);
SensorManager manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor accelerometer = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
}
@Override
public void onSensorChanged(SensorEvent event) {
float xChange = history[0] - event.values[0];
float yChange = history[1] - event.values[1];
history[0] = event.values[0];
history[1] = event.values[1];
if (xChange > 2){
direction[0] = "LEFT";
}
else if (xChange < -2){
direction[0] = "RIGHT";
}
if (yChange > 2){
direction[1] = "DOWN";
}
else if (yChange < -2){
direction[1] = "UP";
}
builder.setLength(0);
builder.append("x: ");
builder.append(direction[0]);
builder.append(" y: ");
builder.append(direction[1]);
textView.setText(builder.toString());
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// nothing to do here
}
}
This code will only provide you with the general direction on the X and Y axis that the phone has moved in. To provide a more fine grained determination of direction (e.g. to attempt to mimic the movement of a computer mouse) you might find that a phone's accelerometer is not fit for purpose.
此代码只会为您提供手机在 X 轴和 Y 轴上移动的大致方向。为了提供更细粒度的方向确定(例如,尝试模仿计算机鼠标的移动),您可能会发现手机的加速度计不适合用途。
To attempt this, I would first set the sensor delay to SensorManager.SENSOR_DELAY_FAST
and create a list of multiple history events so that I could detect movement over time and not be influenced by slight movements in the opposite direction that often happen when taking accelerometer measurements at such a fine level. You would also need to measure the amount of time that has passed to help calculate the accurate measure of movement as suggested in your comments.
为了尝试这个,我首先将传感器延迟设置为SensorManager.SENSOR_DELAY_FAST
并创建多个历史事件的列表,以便我可以随着时间的推移检测运动,而不会受到相反方向的轻微运动的影响,这种运动在以如此精细的速度进行加速度计测量时经常发生等级。您还需要测量已经过去的时间量,以帮助计算您评论中建议的准确运动量度。
回答by renatogsousa
From what I've read, with the sensors one can detect only accelerations and phone orientation. So you can easily detect the start of the movement (and in which direction) and the stop of the movement, since the velocity is changing so there is acceleration (when stoping acceleration is against the velocity direction).
从我所读到的,使用传感器只能检测加速度和手机方向。因此,您可以轻松检测运动的开始(以及运动的方向)和运动的停止,因为速度在变化,因此存在加速度(当停止加速度与速度方向相反时)。
If the phone is moving with constant velocity, the accelerometers will give zero values (linear acceleration which subtracts gravity). So in order to know if the phone is moving you should compute the velocity at each instant, by
如果手机以恒定速度移动,加速度计将给出零值(减去重力的线性加速度)。所以为了知道手机是否在移动,你应该计算每个瞬间的速度,通过
V(t)=V(t0)+a*dt
in which:
其中:
V(t0)
is the known velocity at previous instant,V(t)
is the velocity at current instant,a
is the acceleration (consider the acceleration in previous instant or mean acceleration between previous and current instant).
V(t0)
是前一时刻的已知速度,V(t)
是当前时刻的速度,a
是加速度(考虑前一瞬间的加速度或前一瞬间和当前瞬间之间的平均加速度)。
The problem is that due to the uncertainty of the sensor values, you might end up summing small errors at each instant, which will lead to erroneous velocity values. Probably you'll have to adjust a low pass filter to the values.
问题在于,由于传感器值的不确定性,您可能最终会在每个瞬间汇总小误差,这将导致错误的速度值。可能您必须根据这些值调整低通滤波器。