Android 与谷歌地图相比,使用传感器的指南针性能较差
按照中的示例,我使用Android 与谷歌地图相比,使用传感器的指南针性能较差,android,google-maps,orientation,android-sensors,Android,Google Maps,Orientation,Android Sensors,按照中的示例,我使用传感器。键入加速计和传感器。键入磁场)创建了一个不平滑的指南针 使用一些简单的平滑技术(使用最后n个值的平均值),效果会更好。但当旋转设备时,它与谷歌地图应用程序的功能相差甚远 当使用内置的谷歌地图应用程序时,指南针工作得非常好,没有明显的延迟,没有抖动和平滑360度 这是正确的传感器/API使用,它只是需要更多的平滑? 如果是的话,android API对此有什么帮助吗 对于不太精确的目的,如根据方位在屏幕上旋转地图,您可以使用基于传感器信号和阈值的方法(跳过微小变化并消除
传感器。键入加速计和传感器。键入磁场)创建了一个不平滑的指南针
使用一些简单的平滑技术(使用最后n个值的平均值),效果会更好。但当旋转设备时,它与谷歌地图应用程序的功能相差甚远
当使用内置的谷歌地图应用程序时,指南针工作得非常好,没有明显的延迟,没有抖动和平滑360度
这是正确的传感器/API使用,它只是需要更多的平滑?
如果是的话,android API对此有什么帮助吗 对于不太精确的目的,如根据方位在屏幕上旋转地图,您可以使用基于传感器信号和阈值的方法(跳过微小变化并消除抖动),而无需任何附加API或库。一般来说是这样的:
...
private static final ALPHA = 0.095;
private static final THRESHOLD = 0.75;
...
// get current bearing value
SensorManager.getOrientation(rotationMatrix, mOrientationAngles);
float currentMeasuredBearing = (float) (Math.toDegrees(mOrientationAngles[0]));
// process 0 transition
if (currentMeasuredBearing < 0) {
currentMeasuredBearing += 360;
}
// apply exponential smoothing (select trend of bearing)
currentMeasuredBearing = mLastMeasuredBearing + (float) ALPHA * (currentMeasuredBearing - mLastMeasuredBearing);
// apply threshold (skip values less THRESHOLD)
if (Math.abs(Math.toDegrees(mOrientationAngles[0]) - mLastMeasuredBearing) > THRESHOLD){
// do what you need (e.g. rotate map) here
updateCamera(currentMeasuredBearing);
}
我想,如果你真的想发疯,你可以把支持它的设备的陀螺仪数据合并起来。但是,在我的手机上查看谷歌地图,看起来他们使用了一些低通滤波和一些量化(滞后)。用你提到的传感器类型,不应该是你做不到的。我怀疑是否有任何系统API用于此。你怎么能看到谷歌地图是如何做到这一点的?我应该澄清一下,我通过在谷歌地图的透视视图中旋转手机推断出这一点。我没有源代码。
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
...
private static final SAMPLING_PERIOD = 250 * 1000;
private static final ALPHA = 0.095;
private static final THRESHOLD = 0.75;
private GoogleMap mGoogleMap;
private SensorManager mSensorManager;
private Sensor mSensorAccelerometer;
private Sensor mSensorMagneticField;
private float[] mAccelerometer;
private float[] mMagnetic;
private float[] mOrientationAngles = new float[3];
private float mLastMeasuredBearing;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
...
}
@Override
protected void onStart() {
super.onStart();
startSensors();
}
@Override
protected void onStop() {
super.onStop();
stopSensors();
}
private void updateCamera(float bearing) {
CameraPosition oldPos = mGoogleMap.getCameraPosition();
CameraPosition pos = CameraPosition.builder(oldPos).bearing(bearing).build();
mGoogleMap.moveCamera(CameraUpdateFactory.newCameraPosition(pos));
}
private void startSensors() {
mLastMeasuredBearing = 0;
if (mSensorAccelerometer != null) {
mSensorManager.registerListener(mSensorEventListener,
mSensorAccelerometer, SAMPLING_PERIOD);
}
if (mSensorMagneticField != null) {
mSensorManager.registerListener(mSensorEventListener,
mSensorMagneticField, SAMPLING_PERIOD);
}
}
private void stopSensors() {
if (mSensorAccelerometer != null && mSensorMagneticField != null) {
mSensorManager.unregisterListener(mSensorEventListener);
}
}
private SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mAccelerometer = event.values.clone();
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
mMagnetic = event.values.clone();
}
if (mAccelerometer != null && mMagnetic != null) {
float[] rotationMatrix = new float[9];
if (SensorManager.getRotationMatrix(rotationMatrix, null, mAccelerometer, mMagnetic)) {
SensorManager.getOrientation(rotationMatrix, mOrientationAngles);
float currentMeasuredBearing = (float) (Math.toDegrees(mOrientationAngles[0]));
// process 0 transition
if (currentMeasuredBearing < 0) {
currentMeasuredBearing += 360;
}
// apply exponential smoothing (select trend of sensors data)
currentMeasuredBearing = mLastMeasuredBearing + (float) ALPHA * (currentMeasuredBearing - mLastMeasuredBearing);
// apply threshold (skip values less THRESHOLD)
if (Math.abs(Math.toDegrees(mOrientationAngles[0]) - mLastMeasuredBearing) > THRESHOLD){
updateCamera(currentMeasuredBearing);
}
mBearingTextView.setText(String.valueOf(Math.round(currentMeasuredBearing)));
mAxisXTextView.setText(String.valueOf(Math.round(Math.toDegrees(mOrientationAngles[0]))));
mAxisYTextView.setText(String.valueOf(Math.round(Math.toDegrees(mOrientationAngles[1]))));
mAxisZTextView.setText(String.valueOf(Math.round(Math.toDegrees(mOrientationAngles[2]))));
mLastMeasuredBearing = currentMeasuredBearing;
}
}
}
};