如何通过 GPS_PROVIDER 获得更高的准确性
Posted
技术标签:
【中文标题】如何通过 GPS_PROVIDER 获得更高的准确性【英文标题】:How to get more accuracy by GPS_PROVIDER 【发布时间】:2014-08-25 12:48:03 【问题描述】:我有一个挑战任务是要获得非常高的准确度。所以我正在使用 GPS_PROVIDER。但我的代码得到不正确的准确性。有时它会显示距离我当前位置 10 到 50 米。有时它会向我显示 距我当前位置 5 到 15 米的距离。我已经测试了 XOLO 和 Sony 两种设备。我已经解决了这些问题,但无法解决。 这是我的代码:-
@Override
protected void onResume()
super.onResume();
if(mMap!= null)
mMaprivate LatLng geo;
map.clear();
locationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
mFragment = (SupportMapFragment) this.getSupportFragmentManager().findFragmentById(R.id.map);
mMap = mFragment.getMap();
setListener();
private void setListener()
System.out.println("setListener() locationListener = "+locationListener);
if(locationListener != null)
clearListener();
Toast toast = Toast.makeText(this, this.getResources().getString(R.string.maps_loading), Toast.LENGTH_LONG);
toast.show();
private LatLng geo;
locationListener = new CustomLocationListener();
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
//criteria.setAccuracy(Criteria.ACCURACY_HIGH);
criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
String bestProvider = locationManager.getBestProvider(criteria, true);
Toast.makeText(this, "bestProvider= "+bestProvider, Toast.LENGTH_SHORT).show();
// locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(bestProvider, 0, 0, locationListener);
handler=new Handler();
timeoutTask = new TimeoutTask(locationListener);
handler.postDelayed(timeoutTask, 50*1000);
private void clearListener()
if(locationListener != null)
locationManager.removeUpdates(locationListener);
locationListener = null;
private void gotLocation(Location location)
loc = location;
System.out.println("getLocation = "+location.getLatitude());
// Toast.makeText(getBaseContext(), "new Lat = "+location.getLatitude(), Toast.LENGTH_LONG).show();
public class CustomLocationListener implements LocationListener
private boolean isCompleted = false;
public CustomLocationListener()
@Override
public void onLocationChanged(Location location)
isCompleted=true;
System.out.println("onLocationChanged 1");
// Called when a new location is found by the GPS location provider.
if(isBetterLocation(location, loc))
// Toast.makeText(getBaseContext(), "yes", Toast.LENGTH_LONG).show();
System.out.println("onLocationChanged 2");
gotLocation(location);
System.out.println("onLocationChanged 3");
clearListener();
setUserPoint();
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
@Override
public void onProviderEnabled(String provider)
@Override
public void onProviderDisabled(String provider)
public boolean isCompleted()
return isCompleted;
private LatLng geo;
private LatLng geo;
public class TimeoutTask implements Runnable
private CustomLocationListener listener;
public TimeoutTask(CustomLocationListener listener)
this.listener=listener;
@Override
public void run()
// TODO Auto-generated method stub
if (listener == null || listener.isCompleted())
Log.e("provider", "completed");
else
Toast.makeText(ScorecardMapViewActivity.this, "We were unable to find your position, please try again", Toast.LENGTH_LONG).show();
Log.e("provider", "timeout");
clearListener();
setUserPoint();
if(goToScorecardStep3WithLocation) finish();
protected boolean isBetterLocation(Location location, Location currentBestLocation)
if (currentBestLocation == null)
// A new location is always better than no location
return true;
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer)
return true;
// If the new location is more than two minutes older, it must be worse
else if (isSignificantlyOlder)
return false;
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate)
return true;
else if (isNewer && !isLessAccurate)
return true;
else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider)
return true;
return false;
private LatLng geo;
private void setUserPoint()
if(!goToScorecardStep3WithLocation)
if(loc != null)
if(handler != null) System.out.println("removed timeout task from handler");
handler.removeCallbacks(timeoutTask);
geo = HelperUtil.getLatLng(loc);
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(geo, 18));
mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
System.out.println("loc.getLatitude() = "+loc.getLatitude());
System.out.println("loc.getLongitude() = "+loc.getLongitude());
// your current position show.
mMap.addMarker(new MarkerOptions().title("Player").position(geo)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.map_point)));
请任何一位专家帮助我。您的帮助将非常有帮助。 谢谢!
更新:-
我注意到我是否在同一个地方。有时我会得到长小数点,有时会得到小数点。由于小数点,计算距离是否有任何影响?我正在计算院子里的距离。
当前位置 = 纬度 28.65361000000004 长 = 77.4122733333333
以前的当前位置点(这是同一个地方,但纬度/经度不同)
纬度 = 28.653685000000003 长 = 77.4123083333334
我有 8 码的距离。我认为一些问题可能是由于长或小的数字点。 有没有办法让我们只得到长小数点?
【问题讨论】:
你在哪里测试你的应用程序??根据 GPS 并非无处不在(即建筑物内)的事实。因此,他们使用其他供应商(WiFi、网络等)以及侧面传感器来提供可能的最佳位置。 精度通常一直在变化(取决于您所在的位置)。您对此无能为力。有些设备有更好的 GPS(比如那些使用 GLONASS 卫星的设备)。 @Sree 是的,我正在户外或露天测试 @Hardy 说的,这完全取决于,我们不知道你是怎么得到的,最好尝试不同的地方和设备,准确度总是会改变 @Hardy 有没有一种方法可以修复它?或任何逻辑 【参考方案1】:消费类 GPS 接收器在 95% 的情况下具有 2.5-6m 的精度,对于移动设备,您无法提高它。
如果您静止不动(通过用户交互告知静止开始和静止结束),您可以计算平均位置。 尤其是在静止不动时,GPS 芯片的精度会降低一些,因为多普勒频移只能在移动时使用。
要计算设备的准确度,您应该采取一些措施,计算平均位置,并计算每次测量到该平均位置的距离。 那么这应该给出3-6m之间的值。
您写道,您希望在静止不动时两个位置之间的距离为 0 米。 但这不适用于 GPS。由于对流层的波动条件,信号延迟略有变化,导致静止不动时的跳跃位置。
如果你启用了 ios 默认使用的静止过滤器,你只会得到 0m。 android 中也应该有可能启用这样的过滤器(例如,通过将距离阈值设置为高于 0 的值)。
【讨论】:
【参考方案2】:在OnLocation
方法中检查定位精度,如果不合适,下次调用OnLocation
通常会更准确。更高的准确性需要更多的工作。您已经看到谷歌地图在该位置周围显示了一个圆圈,并且可能看到它的大小减小了。圆的半径取决于位置精度,它是 Location 的一个属性。
下面的方法效果很好。我在开车、骑自行车、遛狗和哈雷时对它进行了广泛的测试。它会过滤掉进入 Mcd's 并让位置出现在 Mcd 的 wifi 提供商所在的德克萨斯州以及相距 100m 位置的那些讨厌的位置。
@Override
public void onLocationChanged(Location location)
if (!location.hasAccuracy())
return;
if (location.getAccuracy() > myDesiredAccuracy)
return;
//blah what your app does...
isCompleted=true;
System.out.println("onLocationChanged 1");
// Called when a new location is found by the GPS location provider.
if(isBetterLocation(location, loc))
// Toast.makeText(getBaseContext(), "yes", Toast.LENGTH_LONG).show();
System.out.println("onLocationChanged 2");
gotLocation(location);
System.out.println("onLocationChanged 3");
clearListener();
setUserPoint();
注意:有时您会遇到无法获得良好 GPS 接收的死角。这些是由于建筑物内、电源线、视线、高速公路中断、建筑物中未映射的 wifi、其他发射无线电信号的设备干扰 GPS 卫星接收而引起的。基本上任何会干扰无线电接收的东西都会干扰 GPS。
【讨论】:
嗨@danny117 你会设置什么精度设置来跟踪跑步者?我正在构建一个正在运行的应用程序并想知道。 我会在 google 位置提供商处进行 5 秒 40 米。类似于每 5 秒向我发送一次位置信息,但仅限于距离超过 40 米时。以上是关于如何通过 GPS_PROVIDER 获得更高的准确性的主要内容,如果未能解决你的问题,请参考以下文章
使用类似于 Lenet5 的架构对“101 个对象类别”数据进行分类,获得比预期更高的准确度
与 LSTM 中的 sigmoid + binary_crossentropy 相比,使用 softmax + categorical_crossentropy 获得更高的准确度