Местоположение GPS

Я рисую сердце, поскольку полилиния на карте 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?

Ответ 1

Колебание местоположения - это нормальное поведение. Дело в том, когда/как вы должны принять или отказаться от неожиданного местоположения. Как прокомментировал пользователь (Patrick Artner), вы должны отказаться от внезапных побочных движений.

Вы можете отменить эти движения двумя способами,

  • Позволяет решать минимальные критерии (1 метр).

    Предполагая минимальное расстояние в 1 метр, потому что, если человек "идет (не стоит)", это может быть возможно, человек может покрыть, по крайней мере, расстояние 1 метр в "X" секундах. Поэтому, если пройденное расстояние меньше 1 метра, вы можете просто отказаться.

  • Разрешает максимальные критерии (5 метров).

    Предполагая максимальное расстояние 5 метров, потому что, если человек "идет (не работает)", это невозможно, человек может покрыть расстояние более 5 метров в "X" секундах. Поэтому, если пройденное расстояние вернулось более чем на 5 метров, вы можете просто отказаться.

где <

distance = NEW_LOCATION - OLD_LOCATION (Как получить расстояние?)

X = определенное количество времени (в секундах)

Просто примите местоположение менее 5 м и более 1 м (объем расстояния, который вы можете выбрать, согласно вашему пониманию).

Ответ 2

Основы ошибок системы GPS, описанные, например, здесь. Используя Extended Kalman Filter с использованием данных GPS (IMHO необработанные, нефильтрованные данные GPS, полученные от GpsStatus.NmeaListener/OnNmeaMessageListener) и другие датчики (акселерометр, гироскоп, магнитометр и т.д.).) может повысить точность, но сегодня нет возможности создать хорошее приложение с описанной функциональностью (дорожка длиной около 100 м). Если вы упростите путь (например, на рис.)

" Упрощенный

и контрольные точки пересечения маршрутов "геозонность" и его порядок - возможно, вы можете реализовать функциональность, но точность во многих случаях будет неприемлемой.

Ответ 3

Невозможность получения точных координат GPS довольно распространена, так как она зависит от многих факторов, таких как

  • Открытое небо или внутреннее состояние
  • Препятствия, такие как облака, здания.
  • Конфигурация микросхемы GPS на устройстве/мощности ЦП.
  • Уровень сигнала сотовой сети

Вы можете сделать некоторые обходные пути

  • Используйте алгоритм фильтра Кальмана, предложенный @andrii-omelchenko
  • Или вы можете использовать geofencing механизм и установить geofences, и система Android даст вам обратные вызовы при входе/выходе из геозонности

    • A) Установите несколько кругов геосферы (возможно, 3 ~ 5 для следующего набора лат-длин)
    • B) Пометьте шаг как завершен при вводе этого геофорума
    • C) Повторить до тех пор, пока пользователь не заполнит полное сердце.
  • Используйте распознавание активности Android вместе с логикой Geofence, чтобы проверить, является ли пользователь ходьбой или нет.

Ниже приведен пример изображения геозонности, чтобы дать вам представление

введите описание изображения здесь

Ответ 4

Да, местоположение 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();
}

 }

Step2. Сделать этот интерфейс 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);
}

Вы можете позвонить непосредственно под кодом в классе, где необходимо обновить местоположение и удалить службу геопозиционирования.

 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);
        }
    }
}

Спасибо, что это поможет вам.