Местоположение 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);
}
}
}
Спасибо, что это поможет вам.