我在Google地图上绘制一条折线,取决于半径(1 - 100米)。一旦绘制了心脏,用户需要在心脏边界上行走并且需要从头到尾完成(从底部开始然后向左然后向右然后再向下开始)。
我能画出心脏,我得到360分(latlng)。这是我的代码,它将绘制心脏和图像。
private void initPath() {
path = new PolylineOptions();
path.color(ContextCompat.getColor(mActivity,R.color.heart_green));
path.width(25);
// offset to bottom
double offsetY = getY(Math.toRadians(180));
for (int angle = 0; angle <= 360; angle++) {
double t = Math.toRadians(angle);
double x = getX(t);
double y = getY(t) - offsetY;
//Log.d(TAG, "angle = " + angle + "(x = " + x + ",y= " + y + ")");
//convert x,y to lat lng
LatLng latLng = getLatLng(x, y, center);
path.add(latLng);
heart360Points.add(latLng);
}
}
private double getX(double t) {
return radius * 16 * Math.sin(t) * Math.sin(t) * Math.sin(t) / HEART_RATIO;
}
private double getY(double t) {
return radius * (13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t)) / HEART_RATIO;
}
private LatLng getLatLng(double dx, double dy, LatLng centerHeart) {
return new LatLng(centerHeart.latitude + Math.toDegrees(dy / EARTH_RADIUS),
centerHeart.longitude + Math.toDegrees(dx / EARTH_RADIUS) / Math.cos(Math.toRadians(centerHeart.latitude)));
}
但每当我试图在心脏边界上行走时,GPS的位置太多波动,所以我永远无法完成心脏的行走。我目前每秒请求位置。
这是我的位置代码。
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 2000 ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.love_lead_perform);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mApiClient = new GoogleApiClient.Builder(this)
.addApi(ActivityRecognition.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mApiClient.connect();
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mSettingsClient = LocationServices.getSettingsClient(this);
createLocationCallback();
createLocationRequest();
createLocationSettingsRequest();
}
private void createLocationSettingsRequest() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
}
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
我不明白为什么GPS位置波动太大。即使我站着,我也会得到不同的GPS位置。
如何获得准确的GPS定位?
答案 0 :(得分:4)
位置波动是正常行为。问题是,何时/如何接受或丢弃意外的位置。正如用户(Patrick Artner)评论的那样,你应该抛弃突然的侧移。
您可以通过两种方式放弃这些动作,
让我们决定最低标准(1米)。
假设最小距离为1米,因为在人类“行走(不站立)”的情况下,人类可以在'X'秒内至少覆盖1米的距离。因此,如果覆盖的距离小于1米,您可以简单地丢弃。
让我们确定最高标准(5米)。
假设最大距离为5米,因为如果人类“行走(不跑步)”,这是不可能的,人类可以在'X'秒内覆盖超过5米的距离。因此,如果覆盖的距离超过5米,您可以简单地丢弃。
其中,
距离= NEW_LOCATION - OLD_LOCATION(How to get distance?)
X =一定的时间(以秒为单位)
只接受小于5米且超过1米的位置(根据您的理解,您可以选择的距离范围)。
答案 1 :(得分:3)
描述了GPS系统错误的基础知识,例如here。使用Extended Kalman Filter融合来自GPS的数据(恕我直言,未过滤,从GpsStatus.NmeaListener / OnNmeaMessageListener收到的GPS数据)和其他传感器(加速度计,陀螺仪,磁力计等)可以改善准确性,但今天没有可能创建具有所述功能的良好应用程序(轨道路径大约100米&#34;复杂&#34;图)。如果你简化路径(如图所示)
并跟踪交叉检查站&#34;地理围栏&#34;它的顺序 - 可能是你可以实现功能,但在许多情况下准确性是不可接受的。
答案 2 :(得分:2)
没有获得精确的GPS坐标是很常见的,因为它取决于许多因素,如
你可以做一些解决方法
或者你可以使用geofencing机制并设置地理围栏,而android系统将为你提供进入/退出地理围栏的回调
使用Android activity recognition以及上述地理围栏逻辑检查用户是否行走。
下面是示例地理围栏图片,为您提供一个想法
答案 3 :(得分:2)
是的gps位置波动是正常的,但如果你想要更准确的做一件事。在这里,我告诉你我的伎俩。
我确定你也做同样的事情。只是告诉你我的方式。
步骤1.制作此课程 GoogleLocationService.java 强>
public class GoogleLocationService {
private GoogleServicesCallbacks callbacks = new GoogleServicesCallbacks();
LocationUpdateListener locationUpdateListener;
Context activity;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 2000;
public GoogleLocationService(Context activity, LocationUpdateListener locationUpdateListener) {
this.locationUpdateListener = locationUpdateListener;
this.activity = activity;
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
//Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(callbacks)
.addOnConnectionFailedListener(callbacks)
.addApi(LocationServices.API)
.build();
createLocationRequest();
mGoogleApiClient.connect();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private class GoogleServicesCallbacks implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
@Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
Toast.makeText(activity, "Google play service not updated", Toast.LENGTH_LONG).show();
}
locationUpdateListener.cannotReceiveLocationUpdates();
}
@Override
public void onLocationChanged(Location location) {
if (location.hasAccuracy()) {
if (location.getAccuracy() < 30) {
locationUpdateListener.updateLocation(location);
}
}
}
}
private static boolean locationEnabled(Context context) {
boolean gps_enabled = false;
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
ex.printStackTrace();
}
return gps_enabled;
}
private boolean servicesConnected(Context context) {
return isPackageInstalled(GooglePlayServicesUtil.GOOGLE_PLAY_STORE_PACKAGE, context);
}
private boolean isPackageInstalled(String packagename, Context context) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
public void startUpdates() {
/*
* Connect the client. Don't re-start any requests here; instead, wait
* for onResume()
*/
if (servicesConnected(activity)) {
if (locationEnabled(activity)) {
locationUpdateListener.canReceiveLocationUpdates();
startLocationUpdates();
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Unable to get your location.Please turn on your device Gps", Toast.LENGTH_LONG).show();
}
} else {
locationUpdateListener.cannotReceiveLocationUpdates();
Toast.makeText(activity, "Google play service not available", Toast.LENGTH_LONG).show();
}
}
//stop location updates
public void stopUpdates() {
stopLocationUpdates();
}
//start location updates
private void startLocationUpdates() {
if (checkSelfPermission(activity, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(activity, ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, callbacks);
}
}
public void stopLocationUpdates() {
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, callbacks);
}
}
public void startGoogleApi() {
mGoogleApiClient.connect();
}
public void closeGoogleApi() {
mGoogleApiClient.disconnect();
}
}
<强>第二步。制作这个界面 LocationUpdateListener.java 强>
public interface LocationUpdateListener {
/**
* Called immediately the service starts if the service can obtain location
*/
void canReceiveLocationUpdates();
/**
* Called immediately the service tries to start if it cannot obtain location - eg the user has disabled wireless and
*/
void cannotReceiveLocationUpdates();
/**
* Called whenever the location has changed (at least non-trivially)
* @param location
*/
void updateLocation(Location location);
/**
* Called when GoogleLocationServices detects that the device has moved to a new location.
* @param localityName The name of the locality (somewhere below street but above area).
*/
void updateLocationName(String localityName, Location location);
}
您可以直接在类中需要更新位置的代码下面调用并删除locationservice。
private GoogleLocationService googleLocationService;
googleLocationService = new GoogleLocationService(context, new LocationUpdateListener() {
@Override
public void canReceiveLocationUpdates() {
}
@Override
public void cannotReceiveLocationUpdates() {
}
//update location to our servers for tracking purpose
@Override
public void updateLocation(Location location) {
if (location != null ) {
Timber.e("updated location %1$s %2$s", location.getLatitude(), location.getLongitude());
}
}
@Override
public void updateLocationName(String localityName, Location location) {
googleLocationService.stopLocationUpdates();
}
});
googleLocationService.startUpdates();
and call this onDestroy
if (googleLocationService != null) {
googleLocationService.stopLocationUpdates();
}
如果你看,我做了一件事。 getAccuracy()描述以米为单位的偏差。因此,数字越小,准确度越高。
public void onLocationChanged(Location location) {
if (location.hasAccuracy()) {
if (location.getAccuracy() < 30) {
locationUpdateListener.updateLocation(location);
}
}
}
谢谢希望这对你有所帮助。