Android GPS位置波动

Android GPS位置波动,android,gps,google-maps-android-api-2,google-location-services,Android,Gps,Google Maps Android Api 2,Google Location Services,我在谷歌地图上画的心脏是一条多段线,取决于半径(1-100米)。一旦心脏被绘制出来,用户需要在心脏边界上行走,并且需要从头到尾完成(从底部开始,然后向左,然后向右,然后再次从底部行走) 我能够吸引人心,我得到了360分。这是我的代码,它将绘制心脏和图像 private void initPath() { path = new PolylineOptions(); path.color(ContextCompat.getColor(mActivity,R.color.heart_g

我在谷歌地图上画的心脏是一条多段线,取决于半径(1-100米)。一旦心脏被绘制出来,用户需要在心脏边界上行走,并且需要从头到尾完成(从底部开始,然后向左,然后向右,然后再次从底部行走)

我能够吸引人心,我得到了360分。这是我的代码,它将绘制心脏和图像

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位置波动太大。即使我站着,我也会得到不同的GPS位置


如何获得准确的GPS位置?

介绍了GPS系统错误的基本知识,例如。将来自GPS(IMHO原始、未过滤、从/接收的GPS数据)和其他传感器(加速计、陀螺仪、磁强计等)的数据进行融合可以提高精度,但目前不可能创建具有所述功能的良好应用程序(100米左右的轨迹“复杂”图)。如果简化路径(如图所示)


轨道交叉口检查站“geofence”及其顺序-可能是您可以实现功能,但在许多情况下准确性是不可接受的。

位置的波动是它的正常行为。问题是,何时/如何接受或放弃意外位置。正如用户(Patrick Artner)所评论的,您应该放弃突然的侧面移动

你可以通过两种方式放弃这些动作

  • 让我们决定最低标准(1米)

    假设最小距离为1米,因为在人类“行走(非站立)”的情况下,这是可能的,人类可以在“X”秒内至少走1米的距离。所以,如果覆盖距离小于1米,您可以简单地放弃

  • 让我们决定最大标准(5米)

    假设最大距离为5米,因为在人类“行走(非跑步)”的情况下,这是不可能的,人类可以在“X”秒内超过5米。所以,如果覆盖距离返回超过5米,您可以简单地丢弃

  • 在哪里,

    距离=新位置-旧位置()

    X=一定的时间量(以秒为单位)


    只需接受小于5米和大于1米的位置(您可以根据自己的理解选择距离范围)

    无法获得精确的GPS坐标是很常见的,因为这取决于许多因素,如

    • 露天或室内条件
    • 云层、建筑物等障碍物
    • 设备/CPU电源上的GPS芯片配置
    • 蜂窝网络信号强度
    你可以做一些变通办法

    • 使用@andrii omelchenko建议的卡尔曼滤波算法
    • 或者您可以使用该机制设置geofence,android系统将在您进入/退出geofence时为您提供回调

      • A) 设置少量土工栅栏圈(下一组板条可能为3~5圈)
      • B) 进入该土工围栏时,将步骤标记为完成
      • C) 重复A,直到用户覆盖整个心脏
    • 与上述地理围栏逻辑一起使用,以检查用户是否正在行走

    下面是地理围栏图片示例,让您了解一下


    是的,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();
    }
    
     }
    
     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();
    }
    
    如果你看,我做了一件事。getAccurance()以米为单位描述偏差。因此,数字越小,准确度越高。

    public void onLocationChanged(Location location) {
        if (location.hasAccuracy()) {
            if (location.getAccuracy() < 30) {
                locationUpdateListener.updateLocation(location);
            }
        }
    }
    
    public void onLocation已更改(位置){
    if(location.hasAccurance()){
    if(location.getAccurance()<30){
    位置UpdateListener.updateLocation(位置);
    }
    }
    }
    

    谢谢,希望这能对你有所帮助。

    你在manifest.xml上调用的权限是什么?也许你需要参军——我听说他们比普通人获得更好的GSP数据:)但我认为你并不是唯一一个遇到这个问题的人,甚至连口袋妖怪(我不玩)也一直在地图上摇摆不定。因此,您可能会受到设备上GPS信号的“默认”随机性的影响,这可能会受到您的位置(隧道、建筑物、树木==跟踪GPS所需的卫星)和/或天气的影响-这似乎会影响地理缓存。是的,这是真的,但“Waz3”、“Ub3r”和正确的“G00gle方向”也是真的工作起来很有魅力,动作流畅,精度在几米左右。。。我想他们对我们隐藏了一些秘密,小开发者。@statosdotcom-他们可能会将手机定位数据与gps结合起来,或者根据移动速度平均5到20秒的数据,以消除锯齿形移动。甚至可能放弃基于最近n个位置的向量的突然“侧移”,即大量填充/删除错误数据和预测“好”样本的内容。@PatrickArtner很好的分析和评论,谢谢。你是完全正确的,这不仅仅是一个使用正确工具的问题,而是将其与人类理性方面的知识结合起来,也就是说,不只是盲目地说谎技术数据,而是使用准确的数据来预测发生了什么。人+机器。。。哇。。。我们要去哪里D
    public void onLocationChanged(Location location) {
        if (location.hasAccuracy()) {
            if (location.getAccuracy() < 30) {
                locationUpdateListener.updateLocation(location);
            }
        }
    }