我有以下代码可以完美地适用于我的Nexus 5。
public void onSensorChanged(SensorEvent event) {
float degree = Math.round(event.values[0]);
displayMsg.setText(String.valueOf(degree));
}
degree
包含指南针的方向。我想做的是检测方向的变化。因此,假设一个人向北走,然后向右转10度。一旦这个人改变方向,我希望能够注意到。此外,也存在不确定性。例如,当人向北行走时,方向不是恒定的 0 度。它将在 358 度和 2-3 度之间波动。
我想用Timer.schedule
每 500 毫秒存储一次度数,然后做一个
if(Math.abs(degree - storedDegree) > 10)
Toast.makeText(this,"Direction Changed",Toast.LENGTH_SHORT).show();
但是,我认为由于创建的线程数量,此方法会耗尽内存。有没有更智能/更好的方法来检测方向变化?
更新
这是我正在做的完整代码。
我正在计算步数,我想保持步数的方向。 一旦方向改变 10 度,计步器应该存储它的值(比如在数组列表中(,然后转到 0 并重新开始计数。
boolean start = true;
@Override
public void onSensorChanged(SensorEvent event) {
//------------------------------Compass--------------------------------------
final float degree = Math.round(event.values[0]);
displayMsg.setText(String.valueOf(degree));
//---------------------------------------------------------------------------
Sensor sensor = event.sensor;
float[] values = event.values;
int value = -1;
int steps;
if (values.length > 0) {
value = (int) values[0];
}
if(mode.equals("Start"))
{
if (sensor.getType() == Sensor.TYPE_STEP_COUNTER)
{
if(start)
{
count = value;
start = false;
}
steps = value-count;
stepCounter.setText("Step Counter Detected : " + steps);
}
}
}
我会使用低通滤波器来消除波动。
代码如下:
protected float[] lowPass(float[] input, float[] output) {
if (output == null) return input;
for (int i = 0; i < input.length; i++) {
output[i] = output[i] + ALPHA * (input[i] - output[i]);
}
return output;
}
阿尔法在哪里静态最终浮点数 ALPHA = 0.25f;
我还将发布用于获取"方向"的代码。也许它可以帮助您:
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
mSensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_UI);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
mGravity = lowPass(event.values.clone(), mGravity);
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mGeomagnetic = lowPass(event.values.clone(), mGeomagnetic);
if (mGravity != null && mGeomagnetic != null) {
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
if (success) {
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
azimut = orientation[0]; // orientation contains: azimut, pitch and roll
}
}
}
在此之后,像这样使用方位角:
if (azimut != null) {
canvas.rotate(-azimut * 360 / (2 * 3.14159f), centerx, centery);
if ((azimut > -0.2) && (azimut < 0.2)) current_direction = "North";
if ((azimut > 1.3) && (azimut < 1.7)) current_direction = "East";
if (((azimut < -2.8) && (azimut > -3.2)) || ((azimut < 3.2) && (azimut > 2.8))) current_direction = "South";
if ((azimut > -1.7) && (azimut < -1.3)) current_direction = "West";
}
我认为您的问题与传感器有关,而不是您的逻辑。你可以试试这个,但我并没有真正失败传感器。 我知道定位服务可以为您提供设备轴承(通过GPS(,这也是一种选择。
您能否检查当前度数的变化是否超过阈值,然后使用新度数更新存储值?
一个可能的例子是这样的:这个想法是,由于每当更新值时都会调用onSensorChanged,因此您可以检查当前度数和存储值之间的差异是否超过某个阈值。如果是采取行动并存储新学位,则直接忽略更改。
private float storedDegree;
public void onSensorChanged(SensorEvent event) {
if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
float degree = Math.round(event.values[0]);
if(Math.abs(degree - storedDegree) > 10) {
Toast.makeText(this,"Direction Changed",Toast.LENGTH_SHORT).show();
displayMsg.setText(String.valueOf(degree));
storedDegree = degree;
}
}
}